<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>StudioWorks - swGui5</title> <meta name="keywords" content="omnis studio, raining data, studioworks documentation" /> <link rel="stylesheet" type="text/css" href="http://www.studiotips.net/css/codedoc.css" /> <link rel="stylesheet" type="text/css" href="http://www.studioworks-dev.net/css/codedoc.css" /> </head> <body> <div id="container"> <p><a href = ../index.html > Sw4 </a> &nbsp &gt; &nbsp <a href = index.html > About </a> &nbsp &gt; &nbsp swGui5</p> <a name="swgui5" /> <h2>swGui5</h2> <p>This section contains concepts, ideas, and discussion, on a new GUI structure that could be added to the StudioWorks framework in the future.</p> There is no time committment on swGui5. It may or may not be added to the framework. <a name="windowcontrollerobjects" /> <h3>Window Controller Objects</h3> <p>The first version of StudioWorks used <em>Window Controller Objects</em>. Each window instance was mapped to a window controller object class. When a window class was instantiated it would find and instantiate its own window controller object class.</p> <p>Much of the code that would normally be in the window class was moved to the window controller object. The expresssion used was <em>"keep the window class dumb, put the intelligence in the wco"</em>.</p> <p>StudioWorks moved away from Window Controller Objects for a couple of reasons:</p> <ol> <li><span class="nav">Instability</span> It was very difficult (impossible?) to keep a stable object class instance in the earlier versions of Omnis Studio. Without warning you could end up with 2 instances and your carefully crafted code would go south.</li> <li><span class="nav">Complexity</span>. It was a signicant step for many developers to move from Omnis Class procedural code to Omnis Studio object-oriented programming. Adding window controller objects to the mix made it even more difficult.</li> <li><span class="nav">Order of Instantiation</span>. The window class had to be instantiated first and then it had to instantiate its Window Controller Object. A cleaner approach would have been to instantiate the Window Controller Object and let it then instantiate the window class, but due to instabiilty of object class instances it had to be done in the reverse order.</li> </ol> <p>In hindsight another problem with Window Controller Objects was that responsibilities between the window class and the window controller object class were never clearly defined. You were never sure whether code would be in the window class or the window controller object.</p> <p>We are now considering reintroducing Window Controller Objects in the StudioWorks framework. To maintain backwards compatabilty the <span class="code">swGui4</span> module would remain as it is, and the Window Controller Object structure would be introduced in a new module, <span class="code">swGui5</span>.</p> <p>The reasons for reintroducing Window Controller Objects to the StudioWorks framework are as follows:</p> <ol> <li><span class="nav">Object Reference Datatype</span> - Omnis Studio has introduced a new data type, <span class="code">Object Reference</span>, which solves the instability problems we had with the <span class="code">Object</span> data type.<br /> <br /> The new <span class="code">Object Reference</span> datatype can instantiate an object class on its own. No need to live inside another instance. Therefore a window controller object can be instantiated and it can then instantiate and construct its window instance. The only trick with the <span class="code">Object Reference</span> datatypes is that the developer must delete the instance when they are finished with them or they will continue to live in memory until you quit Omnis Studio. (However they could be situations where this could be used to our advantage.)</li> <li><span class="nav">Separation of Visual and Non-Visual Code</span> - Moving all but the basic event handling and field decoration code to Window Controller Object methods would simplify and greatly reduce the window class code. With clearly defined Window Controller Object vs. window class responsibilities we could reuse window controller object code for remote forms and ultrathin client web apps.</li> <li><span class="nav">Better Class Structure</span> - The current superclass/subclass window class structure in <span class="code">swGui4</span> is getting a bit unweildy. By the time you get 4 levels down in the superclass/subclass struture there are a lot of superclass methods, not all of which are useful to your particular window instance. The fact that they are not listed in alphabetic order doesn't help the situation. It can be quite a job debugging methods which call up 4 levels of <span class="code">Do inherited</span>. The goal with introducing Window Controller Objects would be to <em>flatten</em> the class structure. The window controller object can contain just the methods required for a particular window instance and can call other helper object methods as needed.</li> </ol>The downside on introducing Window Controller Objects is that complexity will increase because each window controller object can involve numerous other helper objects. The Window Controller Object objects can also have a superclass/subclass structure. Dependencies and coupling would increase. But you can't have the cake and eat it. With clearly defined roles and adherence to the rules, window controller objects could reduce code, increase reuse, flatten inheritence, and increase flexibility. <a name="wcoresponsibilities" /> <h3>WCO Responsibilities</h3> <p>The following is a list of ideas on the responsibilities of the window controller object classes.</p> <ol> <li><span class="nav">Non-Visual Object</span></li><ol> <li>The Window Controller Object <strong>never</strong> prompts the user on its own. The Window Controller Object can have <span class="code">$prompt...</span> methods, but these can only be called by window class methods.</li> <li>The Window Controller Object <strong>never</strong> calls the error handler <span class="code">$promptonceLastError</span> method. The window controller object just has to return the flag or return value.</li> </ol> <p> <li> <span class="nav">Modeless Prompts</span> - if asked to prompt the user via a <span class="code">$prompt...</span> method, always use the modeless prompts so that the same code could be used for a web app. The <span class="code">$prompt..._continue</span> method would be a window controller object method, not a window class method.</p> <p> <li> <span class="nav">Event Handling</span> - <span class="code">$event</span> and <span class="code">$control</span> methods would <strong>not</strong> be found in the Window Controller Object.</p> <p> <li> <span class="nav">Event Parameters</span> - None of the window controller object methods could directly use Omnis Studio event parameters. All parameters must be passed from the window class to the Window Controller Object.</p> <li> <span class="nav">Redraw</span> - The window class methods are responsible for <span class="code">$redraw</span>. <strong>Never</strong> include <span class="code">$redraw</span> in the Window Controller Object code.<br /> </ol> <a name="windowclassresponsibilities" /> <h3>Window Class Responsibilities</h3> <p>; Do pContextMenu.$addMenuLine(pMnID,pbElipsis,pMenuText)</p> <p>; Can we modify the schema class?<br /> Do $cinst.$canModifyClass() Returns bCanSave<br /> If not(bCanSave)<br /> Calculate Text as con("Read-only: ",$cinst.iClassName," needs to be checked out of the VCS.")<br /> Do pContextMenu.$addMenuLine($cinst,'doNothing',kFalse,Text)<br /> Else</p> <p>Do irTree.$currentnode() Returns rCurrNode<br /> Do irTree.$getselectednodes(List)</p> <p>; $addMenuLine(pfObserver,pMenuID,pbEllipsis,pMenuText_opt)</p> <p>; Only allow new if one line selected.<br /> If List.$linecount=1<br /> Do pContextMenu.$addMenuLine($cinst,'newNode',kTrue,'New')<br /> End If</p> <p>; Only allow duplicate if one line selected and not a root node.<br /> If List.$linecount=1&amp;rCurrNode.$level<>1<br /> Do pContextMenu.$addMenuLine($cinst,'duplicateNode',kTrue,'Duplicate')<br /> End If</p> <p>; Only delete selected if one line selected and not a root node.<br /> If List.$linecount>0&amp;rCurrNode.$level<>1<br /> Do pContextMenu.$addMenuLine($cinst,'deleteSelectedNodes',kTrue,'Delete Selected')<br /> End If</p> <p>; Only allow duplicate if one line selected and not a root node.<br /> If List.$linecount=1&amp;rCurrNode.$level<>1<br /> Do pContextMenu.$addMenuLine($cinst,'editNode',kTrue,'Edit')<br /> End If</p> <p>End If<br /> End If<br /> Quit method FlagOKThe following is a list of ideas on the responsibilities of a window class that uses a window controller object.</p> <ol> <li><span class="nav">Event Handling</span> - All event handling is the responsibility of the window class.</li> <li><span class="nav">Field Decoration</span> - Decorating fields is the responsibilty of the window class.</li> <li><span class="nav">Field Properties</span> - setting the field properties is the responsiblity of the window class.</li> <li><span class="nav">Window Size</span> - save and restore window size for each user is the responsiblity of the window class.</li> <li><span class="nav">Field Sizes</span> - save and restore list column widths, treelist widths, etc. is the responsiblity of the window class.</li> <li><span class="nav">Prompt User</span> - the decision to prompt the user for input is the responsiblity of the window class. The window class can delegate this by calling a <span class="code">$prompt...</span> method in the Window Controller Object, but the decision to prompt is alway made by the window class. The sequence of code that follows the prompt which we delegate to the Window Controller Object would be the responsibility of the Window Controller Object. Problem - What if the window needs to be redrawn to show the new information? Can the Window Controller Object tell the window to redraw? This may have to be an exception to the no $redraw rule.</li> <li><span class="code">Error Prompt</span> - If an error is logged by the Window Controller Object, the window class is reponsible to send a <span class="code">$promptonceLastError</span> to the error handler.</li> <li><span class="nav">Redraws</span> - the window class is responsible for redrawing itself or specific objects.</li> </ol> <a name="datalists" /> <h3>Data Lists</h3> <p>Should datalists be in the window class or the Window Controller Object?</p> <p>It is tempting to consider storing all the datalists in the Window Controller Object and having window objects (headed list, complex grid, etc.) <em>reference</em> the datalists in the Window Controller Object.</p> <p>Once advantage of doing this is that it might make it simpler to have 2 different window instances (stand alone or as subwindows) with different presentations of the same data pointing to the same Window Controller Object datalist. One window might be a list, the other a graph, one might display the visible fields of the current row, the other other all of the rows but just one or two columns of the datalist.</p> <p>The Window Controller Object can decide if 2 different windows under its control point to the same datalist or separate datalists.</p> <p>Another possible adavantage of storing the datalist in the Window Controller Object is that you can keep a Window Controller Object instance alive even if the window instance is closed. If the window instance is reopened the same Window Controller Object instance could be used with the datalist still populated.</p> <p>Referencing datalists was not always stable in the earlier versions of Omnis Studio. This has not been a problem in the later versions of Omnis Studio.</p> For ultrathin web apps you can not reference a Window Controller Object datalist, the datalist must be passed to the ultrathin web client... so we can only go so far with referencing the Window Controller Object datalist. That might be a reason for storing the datalist in the window class rather than the Window Controller Object. <a name="sequenceofinstantiation" /> <h3>Sequence of Instantiation</h3> <p>What is the sequence of instantiation?</p> <ol> <li>Is the Window Controller Object instantiated first, and then does it instantiate the window class?</li> <li>Or is the window class instantiated first and does it then instantiate its Window Controller Object?</li> </ol> <p>I am leaning towards option #1 because it may provide more flexibility. Numerous window classes in StudioWorks are completely generic and reused for many different window instances.</p> <p>If we have a window controller object class for each wininstid, we would just have to instantiate the window controller object and let it instantiate the window class.</p> <p>However, this will be a problem for subwindows. The <span class="code">$classname</span> of the subwindow field must be assigned first and when it is assigned the window class is <em>immediately</em> instantiated. The work around could be to send an <span class="code">$openWCO</span> message to the oWindows object.</p> <p><span class="code">Do wn.$openWCO(pWinInsID) Return WCOInstName</span></p> <p>Then set the subwindow field <span class="code">$parameters</span> property to include the <span class="code">WinInstID</span> and the <span class="code">WCOInstName</span>. The <span class="code">$construct</span> method of the window instance receives the <span class="code">WCOInstName</span> as an optional second parameter and if received, it sends a <span class="code">$retWCORef</span> message to <span class="code">oWindows</span>.</p> <p><span class="code">Do wn.$retWCORef(pWCOName) Returns ioWCO</span></p> <p>The return value is a pointer to the Window Controller Object object reference instance which is stored in a list of Window Controller Object object reference instances.</p> <p>If the second parameter is empty, the window's $construct methods sends the <span class="code">WinInstID</span> as the parameter to <span class="code">oWindows</span>.</p> <p><span class="code">Do wn.$retWCORef(pWinInstID) Returns ioWCO</span></p> <span class="code">oWindows</span> then creates a new Window Controller Object object reference instance and passes it back. <p class="footer">StudioWorks Documentation - Copyright 2005 Vencor Software </p></div> </body> </html>