Headline

GUI programming in Language:Haskell with Technology:wxHaskell

Motivation

The implementation demonstrates GUI programming in Language:Haskell with Technology:wxHaskell. A simple GUI for companies is provided. The user can navigate the hierarchical company structure, cut salaries, and edit attributes such as names, addresses, and salaries. The implementation uses a zipper-inspired focus concept to enable modification of the company tree along editing in the GUI. The focus keeps track of a location in the company tree and enables read and write operations for the location.

Illustration

Focus datatype

We are using a datastructure inspired by the concept of Zippers to specify positions of components within the company. We provide an algebraic datatype

Focus
:

data Focus = 
     CompanyFocus
   | DeptFocus [Int]
   | ManagerFocus [Int]
   | EmployeeFocus [Int] Int
    deriving (Show, Read)

We define one constructor per company datatype and one for managers. For example to construct a focus for an employee one needs to pass:

  • A list of indexes: Starting from the company root this list is used to navigate through the departments and subdepartments to the employee's department.
  • An index: The index of this employee in the employee's department's employees list.
On top of this definition we provide functions to get sub and upper foci and to read and write company components (see this!!Focus.hs for details).

The views

For each company datatype, that is

Company
,
Department
and
Employee
, this!!Views.hs provides a view to display the specific component including buttons to navigate and cut salaries. All of these functions are of type
Frame () -> Focus -> Company -> IO ()
. That is, given the global frame, a focus and a company these functions perform GUI actions (which are IO actions). In the following we demonstrate how an employee is displayed.

Viewing an employee

showEmployee
is the view function for employees:

viewEmployee :: Frame () -> Focus -> Company -> IO ()
viewEmployee f focus c = do
    -- reading employee
    let e = readEM focus c
    -- setting up frames and panels
    set f [ text := "Employee \"" ++ ename e ++ "\""]
    p <- panel f [textColor := textBlue]
    -- boxes for name, address and salary
    nameBox <- entry p [text := ename e]                                    
    addressBox <- entry p [text := address e]
    salaryBox <- entry p [text := show $ salary e]
    -- cut button
    cButton <- cutButton p f focus c
    -- back button                                
    bButton <- backButton p f focus c           
    -- save button                                                             
    sButton <- button  p 
          [ text := "Save"
          , size := Size 50 22 
          , on command := do { 
              newName <- get nameBox text;
              newAddress <- get addressBox text;
              newSalary <- get salaryBox text;
              objectDelete p;
              viewEmployee f focus $ 
               writeEM focus c $ 
                Employee newName newAddress $ 
                 read newSalary; }]
    -- compose layout                                 
    setEmployeeLayout f p sButton bButton nameBox addressBox salaryBox cButton

In line 4 we read the employee in question using the Focus module's function

readEM
. In lines 6-7 we set the frame title and create a new panel for this view. In lines 9-11 we create one input box per employee field. We create buttons to cut the employee's salary and to go back to the department level in lines 13-15. In lines 17-28 we set up a save button: When a user clicks the button, the name, address and salary fields are read, the panel is deleted, the employee is updated in the company and the new company is displayed. In the last line we call
setEmployeeLayout
, which composes the layout using various layout combinators (see this!!Views.hs for details).

Cutting button

On each view the GUI provides a button to cut all salaries:

cutButton :: Panel () -> Frame () -> Focus -> Company -> IO (Button ())
cutButton p f focus c = 
  button p [ text := "Cut"      
           , size := Size 50 22                                                                
           , on command := do {
                objectDelete p; 
                view f focus $ readCutWrite focus c;}]   

When the user clicks the button the

command
action (lines 5-7) is executed. First the view's panel is deleted in line 6. We use
readCutWrite
to cut the company component's salaries. This function reads the component in question based on the focus, then cuts this component's salaries and replaces it in the given company. In line 7 the
command
action calls
view
to view the company, department or employee. Based on the focus
view
decides which concrete view-function to call:

view:: Frame () -> Focus -> Company -> IO ()
view f focus = view' f focus
  where 
    view' = case focus of
              CompanyFocus        -> viewCompany
              (DeptFocus  )       -> viewDept
              (EmployeeFocus    ) -> viewEmployee
              (ManagerFocus  )    -> viewEmployee       

Starting the GUI

We use xwHaskell's

start :: IO a -> IO ()
. This function runs the given GUI of type
IO a
while discarding
a
and returning
IO ()
:

gui :: IO ()
gui = do
    f <- frame [ textBgcolor := colorRGB 112 128 144 
               , resizeable := False
               , fontWeight := WeightBold
               , fontUnderline := False
               , position := Point 50 50]
    showCompany f CompanyFocus company 

main :: IO ()
main = start gui

In lines 3-7

gui
creates the main frame for all views passing a list attributes, which are assigned by making use of assign operator
(:=)
. In the last line the function calls
showCompany
passing the frame, the root focus and a sample company in line 8.

Architecture

this!!Views.hs provides one view per company datatype. this!!Main.hs starts the GUI. The algebraic datatype for companies can be found in this!!Company.hs, a sample company in this!!SampleCompany.hs. this!!Focus.hs provides a focus datatype and functions on top of it. this!!Total.hs and this!!Cut.hs provide functionality to total and cut salaries.

Usage

  • this!!Main.hs has to be compiled using GHC.
  • The output is executed.
There is a Makefile with a target start covering both stepts.


There are no revisions for this page.

User contributions

    This user never has never made submissions.

    User edits

    Syntax for editing wiki

    For you are available next options:

    will make text bold.

    will make text italic.

    will make text underlined.

    will make text striked.

    will allow you to paste code headline into the page.

    will allow you to link into the page.

    will allow you to paste code with syntax highlight into the page. You will need to define used programming language.

    will allow you to paste image into the page.

    is list with bullets.

    is list with numbers.

    will allow your to insert slideshare presentation into the page. You need to copy link to presentation and insert it as parameter in this tag.

    will allow your to insert youtube video into the page. You need to copy link to youtube page with video and insert it as parameter in this tag.

    will allow your to insert code snippets from @worker.

    Syntax for editing wiki

    For you are available next options:

    will make text bold.

    will make text italic.

    will make text underlined.

    will make text striked.

    will allow you to paste code headline into the page.

    will allow you to link into the page.

    will allow you to paste code with syntax highlight into the page. You will need to define used programming language.

    will allow you to paste image into the page.

    is list with bullets.

    is list with numbers.

    will allow your to insert slideshare presentation into the page. You need to copy link to presentation and insert it as parameter in this tag.

    will allow your to insert youtube video into the page. You need to copy link to youtube page with video and insert it as parameter in this tag.

    will allow your to insert code snippets from @worker.