User:Thepigdog/GUI Theory

From Knowino
Jump to: navigation, search

Contents

[edit] Purpose

The goal of this page is to describe the general theory of designing and implementing Graphical User Interfaces.

[edit] Introduction

A graphical user interface is an interface that a human uses to interact with a computer that allows the user to see a representation of objects and select and interact with the objects by pointing to them using a graphical input device.

Implementation of GUIs is normally done using the Model View Controller architecture. There are certain limitations to this architecture that I would like to highlight.

[edit] The Starting Point

A user wishes to interact with an object.

The simplest approach is for the object to draw itself. Every object implements a draw method. Drawing an object proceeds by drawing all the component objects out of which the object is made. Drawing is a traversal of the object structure.

There are problems with this approach.

These considerations lead directly to the View/Model separation. The view is one appearance of the object. The object exists independently of its appearance.

But this approach has problems.

These are both serious problems that have added significantly to the mess in GUI code.

[edit] GUI Objects

We require the Model to be a description of the object independent of any requirement to display the object. The view must then be everything else. And there might be multiple views. The common functionality goes into the GUI Objects. The logic for display of a view is called the presentation layer.

The common logic is related to attributes of an object.

The defaulting may only be appropriate in the context of a GUI. All the above functionality should be implemented by functions in the GUI object.

The implementation of these functions should logically be based on the object. It makes sense for the GUI Object to inherit from the Object.

We need CalcEnabled, CalcMandatory, Get and Set methods for each attribute. To avoid confusion we can include the attribute name in the function name. For example for attributes called Quantity and Amount we would have methods.

The Get and Set methods may be inherited from the Object. The Set method may be overridden in the GUI object to provide defaulting functionality specific to the GUI.

These functions could be used as Call Back functions. The functions could be stored on controls or widgets to be called when necessary. But the use of Call Back functions uses second order logic. It is also fairly unnatural.

We would like the name of the function to automatically cause it to be called at the right time. We would like when the control/widget for Quantity calls CalcEnabled, the CalcEnabledQuantity function is called.

I call this mechanism "Renaming Inheritance".

[edit] Renaming Inheritance

Renaming Inheritance is similar to VB events. In VB a variable may be declared using the WithEvents keyword.

For example we could have a VB class called ControlView, which has methods,

Then we declare in VB,

 private Quantity as ControlView

Then there are two event handling methods we can declare,

 private function Quantity_CalcEnabled as boolean
 private function Quantity_CalcMandatory as boolean

Renaming Inheritance is a slightly different twist on VB events. Instead of considering Quantity to be a member variable we think of it as inheriting Quantity with renaming,

In ControlView we declare functions

 CalcEnabled Renamed CalcEnabled%
 CalcMandatory renamed CalcMandatory%
 GetString renamed Get%
 SetString renamed Set%

Then GUIMyObject can be declared

 GUIMyObject
   IsA MyObject
   HasA ControlView Named Quantity

Which gives us 4 functions that can be overridden,

The advantage of this approached is that instead of creating an independent event handling mechanism, Renaming Inheritance extends the inheritance idea. It also hides the member variable.

Direct access to member variable builds inflexibility. Code written which accesses a member variable cant be readily changed to use data stored elsewhere. This kind of code is then inflexible and represents poor design.

See,

[edit] The structure of a GUI object

For an object MyObject with attributes Quantity and Amount, we would have,

 MyObject
 {
   has DoubleAttribute named Quantity
   has DoubleAttribute named Amount
 }
 GuiMyObject
 {
   is MyObject
   has DoubleControl named Quantity
   has DoubleControl named Amount
 }

DoubleAttribute would have Get and Set methods,

 class DoubleAttribute
 {
   function GetString renamed Get% as String
   function SetString renamed Set% (newVal as String)
 }

DoubleControl would have CalcEnabled, CalcMandatory and Get and Set methods,

 class DoubleControl
 {
   function GetString renamed Get% as String
   function SetString renamed Set% (newVal as String)
   function CalcEnabled renamed CalcEnabled% as Boolean
   function CalcMandatory renamed CalcMandatory% as Boolean
 }

GuiMyObject would inherit the Get and Set methods twice. But instead of the compiler logging an error, we allow multiple function implementations and interpret a call as calling all definitions. This is called "Sharing".

[edit] Sharing

Whenever there are multiple implementations for a function we interpret a call to mean call all of them. This feature can be used when we want to iterate through a structure.

For example StringControl could have a method called Draw. When we want to draw all controls we can call Draw on MyObject. This will call Draw on the StingControls for each object.

Personal tools
Namespaces
Variants
Actions
Navigation
Community
Toolbox