|
@@ -0,0 +1,546 @@
|
|
|
+<html>
|
|
|
+<head>
|
|
|
+<title></title>
|
|
|
+<link rel="styleSheet" href="../bmxstyle.css" type="text/css">
|
|
|
+</head>
|
|
|
+<body>
|
|
|
+<h1>MaxGUI Overview</h1>
|
|
|
+
|
|
|
+<ul>
|
|
|
+<li>Introduction
|
|
|
+<li>Getting Started
|
|
|
+<li>Gadget Layout
|
|
|
+<li>Crossplatform Issues
|
|
|
+<li>Using an EventHook
|
|
|
+<li>Using a Canvas
|
|
|
+<li>Event Hook based Rendering
|
|
|
+<li>Porting from BlitzPlus
|
|
|
+<li>The New Modules
|
|
|
+<li>Under the Hood
|
|
|
+<li>Extending MaxGui
|
|
|
+</ul>
|
|
|
+
|
|
|
+<hr>
|
|
|
+
|
|
|
+<h3>Introduction</h3>
|
|
|
+
|
|
|
+The MaxGui module provides commands to build user interfaces
|
|
|
+for applications programmed in BlitzMax.
|
|
|
+<p>
|
|
|
+The command set originates from the original BlitzPlus "Gadget"
|
|
|
+based names providing a healthy amount of backward
|
|
|
+compatability for users wishing to port code developed in
|
|
|
+BlitzPlus.
|
|
|
+
|
|
|
+
|
|
|
+<h3>Getting Started</h3>
|
|
|
+
|
|
|
+
|
|
|
+The following program opens a small window on the desktop
|
|
|
+that ends when the window is closed.
|
|
|
+<p>
|
|
|
+The code beginning at "While True" is the main event loop
|
|
|
+of the program, it repeats forever waiting for an Event
|
|
|
+to happen, printing the event's details to the output window
|
|
|
+and ending if the event has the ID of EVENT_WINDOWCLOSE.
|
|
|
+<pre class=code>
|
|
|
+' createwindow.bmx
|
|
|
+
|
|
|
+Strict
|
|
|
+
|
|
|
+Import MaxGUI.Drivers
|
|
|
+
|
|
|
+Local window:TGadget
|
|
|
+
|
|
|
+window=CreateWindow("My Window",40,40,320,240)
|
|
|
+
|
|
|
+While True
|
|
|
+ WaitEvent
|
|
|
+ Print CurrentEvent.ToString()
|
|
|
+ Select EventID()
|
|
|
+ Case EVENT_WINDOWCLOSE
|
|
|
+ End
|
|
|
+ End Select
|
|
|
+Wend
|
|
|
+</pre>
|
|
|
+Try moving and sizing the window while the program is running
|
|
|
+and you will see the details of the events that occur printed
|
|
|
+in the debug window of BlitzMax.
|
|
|
+<p>
|
|
|
+Try also modifying the "window=" line in the program with:
|
|
|
+<pre class=code>
|
|
|
+window=CreateWindow("My Window",40,40,320,240,Null,WINDOW_TITLEBAR)
|
|
|
+</pre>
|
|
|
+which will create a Window with only a title bar and no status or
|
|
|
+menu bars. See the documentation for CreateWindow for more details
|
|
|
+of the Window styles supported by MaxGui.
|
|
|
+<p>
|
|
|
+The MaxGui documentation contains working examples for each of
|
|
|
+commands that create gadgets including CreateButton, CreateCanvas,
|
|
|
+CreateComboBox, CreateHTMLView, CreateLabel, CreateListBox,
|
|
|
+CreateMenu, CreatePanel, CreateProgBar, CreateSlider, CreateTabber,
|
|
|
+CreateTextField, CreateToolBar and CreateTreeView.
|
|
|
+<p>
|
|
|
+
|
|
|
+<h3>Gadget Layout</h3>
|
|
|
+<p>
|
|
|
+A Gadget in MaxGui is given pixel coordinates when it is created
|
|
|
+that positions it in it's parent's client area. The client area of
|
|
|
+a Window gadget is inside the window's borders not including the
|
|
|
+space used by any Status or Menu bars.
|
|
|
+<p>
|
|
|
+If a Window is resized MaxGui uses any children's layout settings
|
|
|
+to reposition them within the new size of it's client area.
|
|
|
+<p>
|
|
|
+The SetGadgetLayout is used to control how the Gadget is repositioned
|
|
|
+when it's parent is resized.
|
|
|
+<p>
|
|
|
+By considering each edge of the Gadget independently, the MaxGui
|
|
|
+layout engine repositions each gadget according to each edge's
|
|
|
+rule where the rule is
|
|
|
+<p>
|
|
|
+EDGE_CENTERED - The edge remains a fixed distance from the center of the parent<br>
|
|
|
+EDGE_ALIGNED - The edge is a locked distance away from it's parent's corresponding edge<br>
|
|
|
+EDGE_RELATIVE - The edge remains a proportional distance from the parent's 2 edges<br>
|
|
|
+<p>
|
|
|
+The following code demonstrates a common case of creating a panel
|
|
|
+in a window the size of the window's client area and locking the
|
|
|
+distance of each edge to the correspong edge of the parent window
|
|
|
+(EDGE_ALIGNED rule). The result is that the panel is automatically sized by
|
|
|
+MaxGui when the window is resized filling the entire client area.
|
|
|
+<pre class=code>
|
|
|
+Strict
|
|
|
+
|
|
|
+Import MaxGUI.Drivers
|
|
|
+
|
|
|
+Local window:TGadget
|
|
|
+Local panel:TGadget
|
|
|
+
|
|
|
+window=CreateWindow("My Window",40,40,320,240)
|
|
|
+
|
|
|
+panel=CreatePanel(0,0,ClientWidth(window),ClientHeight(window),window)
|
|
|
+SetGadgetColor panel,200,100,100
|
|
|
+SetGadgetLayout panel,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED
|
|
|
+
|
|
|
+While True
|
|
|
+ WaitEvent
|
|
|
+ Print CurrentEvent.ToString()
|
|
|
+ Select EventID()
|
|
|
+ Case EVENT_WINDOWCLOSE
|
|
|
+ End
|
|
|
+ End Select
|
|
|
+Wend
|
|
|
+</pre>
|
|
|
+By removing the line of code with the SetGadetLayout command you can view the default
|
|
|
+EDGE_CENTERED rule in effect on all edges with the panel retaining it's size
|
|
|
+due to all it's edges being kept a fixed distance from the center
|
|
|
+of the window.
|
|
|
+<p>
|
|
|
+To view rule EDGE_RELATIVE in effect modify the SetGadgetLayout command to read
|
|
|
+"SetGadgetLayout panel,EDGE_RELATIVE,EDGE_RELATIVE,EDGE_RELATIVE,EDGE_RELATIVE".
|
|
|
+<p>
|
|
|
+But wait, there is no discernable change in the resizing behavior between
|
|
|
+rule EDGE_ALIGNED and rule EDGE_RELATIVE???
|
|
|
+<p>
|
|
|
+Unless the panel is created inset from the window client such as
|
|
|
+the result of the following modification:
|
|
|
+<pre class=code>
|
|
|
+panel=CreatePanel(10,10,ClientWidth(window)-20,ClientHeight(window)-20,window)
|
|
|
+</pre>
|
|
|
+you will note the edges are infact being kept a proportional distance
|
|
|
+from the parent's 2 edges when the window is resized.
|
|
|
+<p>
|
|
|
+The fact is that EDGE_ALIGNED and EDGE_RELATIVE have the same effect on Gadget
|
|
|
+edges when the edges are created on the borders of their parent's client area.
|
|
|
+<p>
|
|
|
+
|
|
|
+<h3>Crossplatform Issues</h3>
|
|
|
+<p>
|
|
|
+In general the MaxGUI module should perform identically on Windows,
|
|
|
+Apple and Linux machines. However some care and attention is required
|
|
|
+when testing in regards to how your application will look on each
|
|
|
+platform.
|
|
|
+<p>
|
|
|
+The following are a few issues that if considered should hopefully
|
|
|
+enable you to publish programs that look and function well on a wide
|
|
|
+variety of systems.
|
|
|
+<p>
|
|
|
+Recomended gadget dimensions.
|
|
|
+<p>
|
|
|
+<ul>
|
|
|
+<li>Buttons and ComboBoxes should be 24 pixels high.
|
|
|
+<p>
|
|
|
+Shorter buttons are possible in Windows but they will become cropped
|
|
|
+on Apple systems so it is recomended that when using the default font
|
|
|
+buttons should be created with a height of 24 pixels.
|
|
|
+<p>
|
|
|
+<li>TextFields should be 20 pixels high and accompanying labels lowered 4 pixels.
|
|
|
+<p>
|
|
|
+Again, using the default font settings, the above rule should produce
|
|
|
+good results on all platforms. Often labels will be placed to the left
|
|
|
+or right of TextFields, in which case they should be set 4 pixels lower
|
|
|
+down the screen in order to correctly align with TextFields.
|
|
|
+<p>
|
|
|
+<li>Separate fields in a form by 30 pixels.
|
|
|
+<p>
|
|
|
+When creating a form with multiple TextField gadgets start each
|
|
|
+row 30 pixels below the y position of the previous gadget's positions.
|
|
|
+</ul>
|
|
|
+<p>
|
|
|
+Use the WINDOW_CLIENTCOORDS flag when dependent on client size.
|
|
|
+<p>
|
|
|
+If you are using a fixed size window specify it's size based on the
|
|
|
+required client area using the WINDOW_CLIENTCOORDS style.
|
|
|
+<p>
|
|
|
+Specifying a window's size in the default frame coordinates will
|
|
|
+result in a client area that may be different on different machines
|
|
|
+due to a number of factors including both the version of the computer's
|
|
|
+operating system and certain user preference outside your control.
|
|
|
+<p>
|
|
|
+<p>
|
|
|
+<h3>Using an EventHook</h3>
|
|
|
+<p>
|
|
|
+As an alternative to developing applications that have a single
|
|
|
+main loop that waits then processes events from an eventqueue
|
|
|
+the AddHook command allows a callback function to be used
|
|
|
+to process events as they happen.
|
|
|
+<p>
|
|
|
+This is important for two type of events.
|
|
|
+<p>
|
|
|
+EVENT_GADGETACTION events produced by Slider gadgets with the
|
|
|
+original SLIDER_SCROLLBAR style and EVENT_WINDOWRESIZE events
|
|
|
+that occur when the user is resizing a Window both require
|
|
|
+a hooked type of event processing for best results.
|
|
|
+In both these situations most OS's go into a "modal"
|
|
|
+loop that means a WaitEvent command will only return once
|
|
|
+the user releases the mouse button but with Event hooks
|
|
|
+the code can be called directly from within the OS's own
|
|
|
+modal loop.
|
|
|
+<p>
|
|
|
+The other type of event is EVENT_GADGETPAINT which is generated
|
|
|
+whenever the operating system needs to redraw a Canvas gadget.
|
|
|
+When hooked, drawing code can be executed at the time of the
|
|
|
+event rather than later when the OS returns control to the
|
|
|
+main program, at which time it may have already drawn other
|
|
|
+content above the Canvas.
|
|
|
+<p>
|
|
|
+
|
|
|
+<h3>Using a Canvas</h3>
|
|
|
+<p>
|
|
|
+The following code is a simple example of using Max2D to
|
|
|
+render dynamically into a Canvas Gadget...
|
|
|
+<pre class=code>
|
|
|
+' createcanvas.bmx
|
|
|
+
|
|
|
+Strict
|
|
|
+
|
|
|
+Import MaxGUI.Drivers
|
|
|
+
|
|
|
+Global GAME_WIDTH=320
|
|
|
+Global GAME_HEIGHT=240
|
|
|
+
|
|
|
+' create a centered window with client size GAME_WIDTH,GAME_HEIGHT
|
|
|
+
|
|
|
+Local wx=(GadgetWidth(Desktop())-GAME_WIDTH)/2
|
|
|
+Local wy=(GadgetHeight(Desktop())-GAME_HEIGHT)/2
|
|
|
+
|
|
|
+Local window:TGadget=CreateWindow("My Canvas",wx,wy,GAME_WIDTH,GAME_HEIGHT,Null,WINDOW_TITLEBAR|WINDOW_CLIENTCOORDS)
|
|
|
+
|
|
|
+' create a canvas for our game
|
|
|
+
|
|
|
+Local canvas:TGadget=CreateCanvas(0,0,320,240,window)
|
|
|
+
|
|
|
+' create an update timer
|
|
|
+
|
|
|
+CreateTimer 60
|
|
|
+
|
|
|
+While WaitEvent()
|
|
|
+ Select EventID()
|
|
|
+ Case EVENT_TIMERTICK
|
|
|
+ RedrawGadget canvas
|
|
|
+
|
|
|
+ Case EVENT_GADGETPAINT
|
|
|
+ Local g=CanvasGraphics(canvas)
|
|
|
+ SetGraphics g
|
|
|
+ SetOrigin 160,120
|
|
|
+ SetLineWidth 5
|
|
|
+ Cls
|
|
|
+ Local t=MilliSecs()
|
|
|
+ DrawLine 0,0,120*Cos(t),120*Sin(t)
|
|
|
+ DrawLine 0,0,80*Cos(t/60),80*Sin(t/60)
|
|
|
+ Flip
|
|
|
+
|
|
|
+ Case EVENT_WINDOWCLOSE
|
|
|
+ FreeGadget canvas
|
|
|
+ End
|
|
|
+
|
|
|
+ Case EVENT_APPTERMINATE
|
|
|
+ End
|
|
|
+ End Select
|
|
|
+Wend
|
|
|
+</pre>
|
|
|
+The above code creates a timer that causes an event to occur
|
|
|
+at 60hz (ticks per second).
|
|
|
+<p>
|
|
|
+Each time an EVENT_TIMERTICK is received by the program's main
|
|
|
+event loop it calls RedrawGadget which tells the system to redraw
|
|
|
+our canvas gadget.
|
|
|
+<p>
|
|
|
+The code following the Case EVENT_GADGETPAINT above is where
|
|
|
+the actual drawing takes place.
|
|
|
+<p>
|
|
|
+- of interest -
|
|
|
+<p>
|
|
|
+If you remove two lines of the above code that contain the
|
|
|
+"RedrawGadget canvas" and "Case EVENT_GADGETPAINT" the program
|
|
|
+still appears to function normally.
|
|
|
+<p>
|
|
|
+This is because MaxGUI infact allows you to draw to a canvas
|
|
|
+when ever you want. Drawing in response to an EVENT_GADGETPAINT
|
|
|
+however is better behavior as no drawing code is executed if
|
|
|
+the canvas is obscured or the application has a low refresh rate
|
|
|
+in which case it will be still asked to redraw itself on the
|
|
|
+event an obscured canvas is revealed by window movement from
|
|
|
+above.
|
|
|
+<p>
|
|
|
+
|
|
|
+<h3>Event Hook based Rendering</h3>
|
|
|
+<p>
|
|
|
+As mentioned above the best way to manage redrawing a Canvas
|
|
|
+gadget is with an EventHook.
|
|
|
+<p>
|
|
|
+The following example uses an EventHook to handle events
|
|
|
+at the time of occurance rather than from the WaitEvent()
|
|
|
+queue. You will notice at the bottom of the program that
|
|
|
+infact the main loop does nothing but WaitEvent and all
|
|
|
+the event handling is done inside the TApplet Type.
|
|
|
+<p>
|
|
|
+<pre class=code>
|
|
|
+' rendering a canvas using an EventHook based Applet Type
|
|
|
+
|
|
|
+Strict
|
|
|
+
|
|
|
+Import MaxGUI.Drivers
|
|
|
+
|
|
|
+Type TApplet
|
|
|
+
|
|
|
+ Field window:TGadget
|
|
|
+ Field canvas:TGadget
|
|
|
+ Field timer:TTimer
|
|
|
+
|
|
|
+ Method Render()
|
|
|
+ Local x,y,width,height,t,i
|
|
|
+ width=GraphicsWidth()
|
|
|
+ height=GraphicsHeight()
|
|
|
+ t=MilliSecs()
|
|
|
+ SetBlend ALPHABLEND
|
|
|
+ SetViewport 0,0,width,height
|
|
|
+ SetClsColor 0,0,0
|
|
|
+ SetOrigin width/2,height/2
|
|
|
+ Cls
|
|
|
+ For x=-width/2 To width/2 Step 2
|
|
|
+ y=Sin(t*0.3+x)*height/2
|
|
|
+ DrawLine 0,0,x,y
|
|
|
+ Next
|
|
|
+ End Method
|
|
|
+
|
|
|
+ Method OnEvent(event:TEvent)
|
|
|
+ Select event.id
|
|
|
+ Case EVENT_WINDOWCLOSE
|
|
|
+ End
|
|
|
+ Case EVENT_TIMERTICK
|
|
|
+ RedrawGadget canvas
|
|
|
+ Case EVENT_GADGETPAINT
|
|
|
+ SetGraphics CanvasGraphics(canvas)
|
|
|
+ Render
|
|
|
+ Flip
|
|
|
+ End Select
|
|
|
+ End Method
|
|
|
+
|
|
|
+ Function eventhook:Object(id,data:Object,context:Object)
|
|
|
+ Local event:TEvent
|
|
|
+ Local app:TApplet
|
|
|
+ event=TEvent(data)
|
|
|
+ app=TApplet(context)
|
|
|
+ app.OnEvent event
|
|
|
+ End Function
|
|
|
+
|
|
|
+ Method Create:TApplet(name$)
|
|
|
+ Local a:TApplet
|
|
|
+ Local w,h
|
|
|
+ window=CreateWindow(name,20,20,512,512)
|
|
|
+ w=ClientWidth(window)
|
|
|
+ h=ClientHeight(window)
|
|
|
+ canvas=CreateCanvas(0,0,w,h,window)
|
|
|
+ canvas.SetLayout 1,1,1,1
|
|
|
+ timer=CreateTimer(100)
|
|
|
+ AddHook EmitEventHook,eventhook,Self
|
|
|
+ Return Self
|
|
|
+ End Method
|
|
|
+
|
|
|
+End Type
|
|
|
+
|
|
|
+AutoMidHandle True
|
|
|
+
|
|
|
+Local applet:TApplet
|
|
|
+
|
|
|
+applet=New TApplet.Create("Render Applet")
|
|
|
+
|
|
|
+While True
|
|
|
+ WaitEvent
|
|
|
+Wend
|
|
|
+</pre>
|
|
|
+<p>
|
|
|
+Unfortunately I have obfiscated (made obscure) the
|
|
|
+function of the event hook by wrapping it in an
|
|
|
+Applet object and I have started using big words in
|
|
|
+my sentences.
|
|
|
+<p>
|
|
|
+To be as concise as possible, the TApplet Type declares
|
|
|
+a Class that features an OnEvent Method that with some
|
|
|
+magic in it's constructor (the Create() Method) provides
|
|
|
+an object oriented way for our program to collect events.
|
|
|
+<p>
|
|
|
+Our TApplet implements the rendering sequence
|
|
|
+as featured in the previous example but because
|
|
|
+it does so based on a Hook responds in a more
|
|
|
+well behaved manner when the OS wishes to redraw the
|
|
|
+desktop when it is made visible by some user action
|
|
|
+or told to refresh with the RedrawGadget command.
|
|
|
+
|
|
|
+<h3>Porting from BlitzPlus</h3>
|
|
|
+<p>
|
|
|
+The following are a few issues that you may encounter when
|
|
|
+porting code from BlitzPlus.
|
|
|
+<p>
|
|
|
+
|
|
|
+<h4>Event Codes</h4>
|
|
|
+<p>
|
|
|
+The codes returned by the WaitEvent and EventID commands
|
|
|
+are not the same as BlitzPlus. See the Event Objects docs
|
|
|
+for a list of the constants used in MaxGUI. Numerical
|
|
|
+values have not been documented in order to encourage
|
|
|
+users to use the correct EVENT_NAMES.
|
|
|
+<p>
|
|
|
+New events in MaxGUI include
|
|
|
+<p>
|
|
|
+EVENT_HOTKEYHIT - see SetHotKeyEvent
|
|
|
+<p>
|
|
|
+EVENT_WINDOWACCEPT - a file has been dragged onto the window
|
|
|
+<p>
|
|
|
+EVENT_GADGETPAINT - a canvas gadget needs redrawing
|
|
|
+<p>
|
|
|
+EVENT_GADGETSELECT - the selected state of a TextArea has changed
|
|
|
+<p>
|
|
|
+EVENT_GADGETMENU - the user has clicked the right button on this gadget
|
|
|
+<p>
|
|
|
+EVENT_GADGETOPEN - a node in a TreeViewNode has been expanded
|
|
|
+<p>
|
|
|
+EVENT_GADGETCLOSE - a node in a TreeViewNode has been collapsed
|
|
|
+<p>
|
|
|
+EVENT_GADGETDONE - an HTMLView has finished loading a page
|
|
|
+<p>
|
|
|
+
|
|
|
+<h4>TextArea filters</h4>
|
|
|
+<p>
|
|
|
+TextAreas no longer generate Key Up, Key Down or Key Stroke events.
|
|
|
+<p>
|
|
|
+Instead the new SetGadgetFilter command can be used to install
|
|
|
+a callback routine that is called each time the user presses
|
|
|
+a key with the callback able to accept or reject each key
|
|
|
+by returning either True or False respectively.
|
|
|
+<p>
|
|
|
+
|
|
|
+<h4>Popup Menus</h4>
|
|
|
+
|
|
|
+There is a new PopupWindowMenu command that can be used
|
|
|
+for implementing context menus commonly activated by the
|
|
|
+right mouse button (reported as an EVENT_GADGETMENU for most
|
|
|
+gadgets).
|
|
|
+
|
|
|
+
|
|
|
+<h3>The New Modules</h3>
|
|
|
+<p>
|
|
|
+The three platform specific modules that ship with MaxGui are
|
|
|
+Win32MaxGui.mod, CocoaMaxGui.mod and FLTKMaxGui.mod which provide
|
|
|
+native implementations of MaxGui for Windows, Apple MacOS and
|
|
|
+Linux platforms respectively.
|
|
|
+<p>
|
|
|
+The new Event.mod and EventQueue.mod modules are extensions
|
|
|
+to the BlitzMax system. BlitzMax events provide the necessary
|
|
|
+mechanics of communicating with a MaxGui based application as well
|
|
|
+as providing all BlitzMax applications with events such as
|
|
|
+EVENT_APPSUSPEND, EVENT_APPRESUME and EVENT_APPTERMINATE.
|
|
|
+<p>
|
|
|
+The commands WaitEvent, PeekEvent and PollEvent are the primary
|
|
|
+commands for receiving Events in BlitzMax programs and PostEvent
|
|
|
+can be used for generating Events.
|
|
|
+<p>
|
|
|
+
|
|
|
+<h3>Under the Hood</h3>
|
|
|
+<p>
|
|
|
+The Type TGadget is used in MaxGui to represent all 18 Gadget
|
|
|
+types including:
|
|
|
+<p>
|
|
|
+GADGET_DESKTOP
|
|
|
+GADGET_WINDOW
|
|
|
+GADGET_BUTTON
|
|
|
+GADGET_PANEL
|
|
|
+GADGET_TEXTFIELD
|
|
|
+GADGET_TEXTAREA
|
|
|
+GADGET_COMBOBOX
|
|
|
+GADGET_LISTBOX
|
|
|
+GADGET_TOOLBAR
|
|
|
+GADGET_TABBER
|
|
|
+GADGET_TREEVIEW
|
|
|
+GADGET_HTMLVIEW
|
|
|
+GADGET_LABEL
|
|
|
+GADGET_SLIDER
|
|
|
+GADGET_PROGBAR
|
|
|
+GADGET_MENUITEM
|
|
|
+GADGET_NODE
|
|
|
+GADGET_CANVAS
|
|
|
+<p>
|
|
|
+The TMaxGUIDriver Type defined in maxgui.driver represents the
|
|
|
+gadget factory which is created at startup to produce platform
|
|
|
+specific versions of TGadget on demand.
|
|
|
+<p>
|
|
|
+The type TGadget is actually an abstract class with TWin32Gadget,
|
|
|
+TCocoaGadget and TFLTKGadget being the actual types produced
|
|
|
+depending on the current TMaxGUIDriver.
|
|
|
+<p>
|
|
|
+The types TIconStrip, TGUIFont and TGadgetItem also provide
|
|
|
+an abstract interface to the platform specific implementations
|
|
|
+meaning that like TGadget itself, they are not intended to be
|
|
|
+extended by the user.
|
|
|
+<p>
|
|
|
+<p>
|
|
|
+
|
|
|
+
|
|
|
+<h3>Crossplatform vs Flexibility</h3>
|
|
|
+<p>
|
|
|
+It is expected that most users wanting to create custom
|
|
|
+gadgets that work well across all platforms will find
|
|
|
+the Panel and Canvas gadgets provide adequate Event reporting
|
|
|
+and rendering functionality from which to produce their
|
|
|
+own uber-gadgets.
|
|
|
+<p>
|
|
|
+The cross platform nature of MaxGUI means there are
|
|
|
+implications for those wishing to extend functionality by
|
|
|
+taking advantage of platform specific features that have
|
|
|
+no logical equivalent on other platforms.
|
|
|
+<p>
|
|
|
+Those wishing to do so are encouraged to implement such
|
|
|
+features in separate modules rather than making modifications
|
|
|
+to the BRL modules which are intended only to support the
|
|
|
+core cross platform MaxGUI functionality.
|
|
|
+<p>
|
|
|
+This of course does not mean the the current specification
|
|
|
+of MaxGUI is set in stone, rather, that those wanting to
|
|
|
+interface at a lower level with the Operating System of
|
|
|
+their choice do so in the privacy of their own modules
|
|
|
+rather than becoming muddied in the source of the lowlevel
|
|
|
+platform specific BRL modules.
|
|
|
+
|
|
|
+</body>
|
|
|
+</html>
|