Jump to content

Creating a Workplace Shell "PileOf" Class: Difference between revisions

From EDM2
Ak120 (talk | contribs)
mNo edit summary
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
by [[Bernie Arruza]]
''by [[Bernie Arruza]]''


Let's be creative and think about things in a new way. For instance, you know how objects in the world around you can be manipulated. Your fingers are like a form of user interface. You can pick things up and drop them. From experience, you have an idea of how much those things weigh (you adjust your muscles accordingly) or if they will break (from their composition).
Let's be creative and think about things in a new way. For instance, you know how objects in the world around you can be manipulated. Your fingers are like a form of user interface. You can pick things up and drop them. From experience, you have an idea of how much those things weigh (you adjust your muscles accordingly) or if they will break (from their composition).
Line 14: Line 14:


Because the closest thing to a PileOf object is an OS/2 folder object, let's begin by looking at the differences between the two kinds of objects:
Because the closest thing to a PileOf object is an OS/2 folder object, let's begin by looking at the differences between the two kinds of objects:
<PRE>
{|class="wikitable"
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
!User's action
³User's action   A "regular"     A "regular"   ³
!A "regular" folder object
³                folder object  PileOf object ³
!A "regular" PileOf object
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
|-
³Drag and drop a Adds the new   If the object ³
|Drag and drop a folder from the desktop into a folder or PileOf object.
³folder from the folder to its   is a "pile" of ³
|Adds the new folder to its list of items.
³desktop into a  list of items.  data files, or ³
If the folder object is closed, the folder is added at the end or according to a sorting criteria.
³folder or                      another non-   ³
If the folder holds other folders and it is opened, the new folder can be inserted between folders or placed inside another folder (its position can be modified by sorting criteria).
³PileOf object.  If the folder  folder class, ³
|If the object is a "pile" of data files, or another non-folder class, the drop will not be allowed.
³                object is      the drop will ³
If the object is a "pile" of folders and the PileOf object is closed, the folder will go on top of the other folders.
³                closed, the    not be allowed.³
No other choices will be allowed.
³                folder is added                ³
If the object is a "pile" of folders and the PileOf object is opened, the folder can be inserted in between folders or inside another folder (no sorting criteria is enforced for the folders in the pile).
³                at the end or  If the object ³
|-
³                according to a  is a "pile" of ³
|Drag and drop a non-folder object from the desktop into a folder or PileOf object.
³                sorting        folders and the³
|Adds the new object to its list of items.
³                criteria.      PileOf object ³
If the folder object is closed, the object is added at the end or according to sorting criteria.
³                                is closed, the ³
If the folder holds other objects and it is opened, the new object can be inserted between objects or placed inside another folder (its position can be modified by sorting criteria).
³                If the folder  folder will go ³
|If the object is a "pile" of another object class or the object class being introduced is not in the set of permissible classes, the drop will fail.
³                holds other    on top of the ³
If the object is a closed "pile" of objects of the same class as the object being introduced, or the object introduced is in the set of permissible classes, the object will go on top of the pile. No other choices will be allowed.
³                folders and it  other folders. ³
If the object is an opened "pile" of objects of the same class as the object being introduced, or the object introduced is in the set of permissible classes, the object can be inserted between objects (no sorting criteria is enforced for the objects in the pile).
³                is opened, the  No other       ³
|-
³                new folder can  choices will be³
|Drag two or more objects out of a folder or PileOf object and drop them on the desktop.
³                be inserted    allowed.       ³
|All objects appear on the desktop.
³                between folders                ³
|A new pile with those items is created on the desktop. Their order is maintained. The settings notebook should appear so you can name the pile.
³                or placed      If the object ³
|-
³                inside another  is a "pile" of ³
|Select sorting criteria for the PileOf piles object.
³                folder (its    folders and the³
|Does not apply.  
³                position can be PileOf object ³
|Sorts the piles but not the contents of any of the piles.
³                modified by    is opened, the ³
Each pile maintains its own sort order.
³                sorting        folder can be ³
|-
³                criteria).      inserted in   ³
|Select sorting criteria.
³                                between folders³
|Destructive - All items in the folder are arranged according to sorting criteria. When the folder is closed or reopened, items will reflect sorting criteria.
³                                or inside     ³
|Non-destructive - All items in the pile can be arranged according to sorting criteria, but when you close the pile and reopen it, the original order is preserved.
³                                another folder ³
You can drag and drop objects within the pile to arrange them the way you want. Also, a sort and save option can be included for larger piles.
³                                (no sorting   ³
|-
³                                criteria is   ³
|Insert a PileOf object into a PileOf piles object.
³                                enforced for   ³
|Does not apply.
³                                the folders in ³
|If the PileOf piles object is closed, the new pile goes on top. A dialog offering to change the name of the pile should appear.
³                                the pile).     ³
If the PileOf piles object is opened, the new pile can be inserted between piles but not inside another pile.
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
|-
³Drag and drop a Adds the new   If the object ³
|Desktop area taken up by an opened folder object or PileOf object.
³non-folder     object to its   is a "pile" of ³
|Defaults to 2" x 7" (even if the folder contains only one object).
³object from the list of items.  another object ³
|Because objects appear as a list, which you can scroll down, the list can be made very small (for example, show only two objects).
³desktop into a                  class or the   ³
Defaults to 1" x 3".
³folder or      If the folder  object class   ³
|-
³PileOf object.  object is      being         ³
|Resize the window so that it shows only two of the objects in the contained object.
³                closed, the    introduced is ³
|Some objects might become "hidden" because they are out of view, and the user can forget that the objects exist.
³                object is added not in the set ³
|No problem - the hidden objects can only belong to the classes supported by the PileOf object. You implicitly know what's there.
³                at the end or  of permissible ³
|}
³                according to    classes, the   ³
³                sorting        drop will fail.³
³                criteria.                      ³
³                                If the object ³
³                If the folder  is a closed " ³
³                holds other    pile" of       ³
³                objects and it  objects of the ³
³                is opened, the  same class as ³
³                new object can  the object     ³
³                be inserted    being         ³
³                between objects introduced, or ³
³                or placed      the object     ³
³                inside another  introduced is ³
³                folder (its    in the set of ³
³                position can be permissible   ³
³                modified by    classes, the   ³
³                sorting        object will go ³
³                criteria).      on top of the ³
³                                pile. No other ³
³                                choices will be³
³                                allowed.       ³
³                                              ³
³                                If the object ³
³                                is an opened " ³
³                                pile" of       ³
³                                objects of the ³
³                                same class as ³
³                                the object     ³
³                                being         ³
³                                introduced, or ³
³                                the object     ³
³                                introduced is ³
³                                in the set of ³
³                                permissible   ³
³                                classes, the   ³
³                                object can be ³
³                                inserted       ³
³                                between objects³
³                                (no sorting   ³
³                                criteria is   ³
³                                enforced for   ³
³                                the objects in ³
³                                the pile).     ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Drag two or     All objects     A new pile with³
³more objects   appear on the   those items is ³
³out of a folder desktop.        created on the ³
³or PileOf                      desktop. Their ³
³object and drop                order is       ³
³them on the                    maintained. The³
³desktop.                        settings       ³
³                                notebook should³
³                                appear so you ³
³                                can name the   ³
³                                pile.         ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Select sorting Does not apply. Sorts the piles³
³criteria for                    but not the   ³
³the PileOf                      contents of any³
³piles object.                  of the piles. ³
³                                Each pile     ³
³                                maintains its ³
³                                own sort order.³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Select sorting Destructive--  Non-destructive³
³criteria.      All items in   --All items in ³
³                the folder are  the pile can be³
³                arranged        arranged       ³
³                according to    according to   ³
³                sorting         sorting        ³
³                criteria. When  criteria, but ³
³                the folder is  when you close ³
³                closed or      the pile and   ³
³                reopened, items reopen it, the ³
³                will reflect    original order ³
³                sorting        is preserved. ³
³                criteria.      You can drag   ³
³                                and drop       ³
³                                objects within ³
³                                the pile to   ³
³                                arrange them   ³
³                                the way you   ³
³                                want. Also, a ³
³                                sort and save ³
³                                option can be ³
³                                included for   ³
³                                larger piles. ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Insert a PileOf Does not apply. If the PileOf ³
³object into a                  piles object is³
³PileOf piles                    closed, the new³
³object.                        pile goes on   ³
³                                top. A dialog ³
³                                offering to   ³
³                                change the name³
³                                of the pile   ³
³                                should appear. ³
³                                              ³
³                                If the PileOf ³
³                                piles object is³
³                                opened, the new³
³                                pile can be   ³
³                                inserted       ³
³                                between piles ³
³                                but not inside ³
³                                another pile. ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Desktop area   Defaults to 2" Because objects³
³taken up by an  x 7" (even if   appear as a   ³
³opened folder  the folder      list, which you³
³object or      contains only  can scroll down³
³PileOf object.  one object).    , the list can ³
³                                be made very   ³
³                                small (for     ³
³                                example, show ³
³                                only two       ³
³                                objects).     ³
³                                Defaults to 1" ³
³                                x 3".         ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Resize the     Some objects   No problem--the³
³window so that  might become " hidden objects ³
³it shows only  hidden" because can only belong³
³two of the      they are out of to the classes ³
³objects in the  view, and the   supported by  ³
³contained      user can forget the PileOf    ³
³object.        that the       object. You   ³
³                objects exist.  implicitly know³
³                                what's there. ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
</PRE>
As you can see, the PileOf object class reuses a lot of the code from the WPFolder class. However, it looks and behaves differently.
As you can see, the PileOf object class reuses a lot of the code from the WPFolder class. However, it looks and behaves differently.


Unlike a regular folder, the PileOf object:
Unlike a regular folder, the PileOf object:
* Contains a settings page so the user can specify the type of pile and its behavior.  
* Contains a settings page so the user can specify the type of pile and its behavior.  
* Validates drag/drop to ensure the object being dragged/dropped is the right type.  
* Validates drag/drop to ensure the object being dragged/dropped is the right type.  
* Contains extra items in its popup menu for the manipulation of its contents.
* Contains extra items in its popup menu for the manipulation of its contents.


==PileOf Settings Page==
==PileOf Settings Page==
In the _wpAddSettingsPages method, call the parent first (WPFolder class) and then call the PileOf method:
In the _wpAddSettingsPages method, call the parent first (WPFolder class) and then call the PileOf method:
<PRE>
<pre>
/* Add PileOf settings page */
/* Add PileOf settings page */
ulPageId = _AddPileOfPage(somSelf,hwndNotebook);
ulPageId = _AddPileOfPage(somSelf,hwndNotebook);
 
</pre>
The _AddPileOfPage method fills up the PAGEINFO structure for the PileOf page and invokes the wpInsertSettingsPage method.
The _AddPileOfPage method fills up the PAGEINFO structure for the PileOf page and invokes the wpInsertSettingsPage method.
 
<pre>
PAGEINFO pi;                              /* Variable declaration       */
PAGEINFO pi;                              /* Variable declaration */


pi.cb                  = sizeof(PAGEINFO);
pi.cb                  = sizeof(PAGEINFO);
Line 236: Line 101:
[[Image:PileOF-Fig-1.gif]]
[[Image:PileOF-Fig-1.gif]]


[[Image:PileOF-Fig-1-2.gif]]
[[Image:PileOF-Fig-2.gif]]


Figure 1. PileOf settings page and PileOf settings page with selected items
''Figure 1. PileOf settings page and PileOf settings page with selected items''


As you can see the settings page contains several controls:
As you can see the settings page contains several controls:
 
* A list box to display and choose from all the OS/2 system objects (you can choose one or more). If you choose to have a pile of bitmaps and icons, you select the Bitmap and Icon entries in the list box. Those are the only two classes of objects that you can drop into this PileOf object.  
* A list box to display and choose from all the OS/2 system objects (you can choose one or more). If you choose to have a pile of bitmaps and icons, you select the Bitmap and Icon entries in the list box. Those are the only two classes of objects that you can drop into this PileOf object.  
 
* A set of check boxes for options:
* A set of check boxes for options:
 
** One Class only - When checked, only one item can be selected from the list box (single selection). When unchecked, multiple items can be selected. After multiple items are selected, this button becomes disabled. To reactivate it, reduce the number of selected items in the list box to zero or one.
** One Class only--When checked, only one item can be selected from the list box (single selection). When unchecked, multiple items can be selected. After multiple items are selected, this button becomes disabled. To reactivate it, reduce the number of selected items in the list box to zero or one.
** Spread contents - When checked, the popup menu for this PileOf object contains the Spread Contents menu item. When clicked, a folder/icon view of the contents of the pile is displayed.
** Spread contents--When checked, the popup menu for this PileOf object contains the Spread Contents menu item. When clicked, a folder/icon view of the contents of the pile is displayed.
** Delete if empty - If selected, and if the PileOf object remains empty before shutdown, the PileOf object will be deleted. After all, an empty pile is not a pile. But then, a pile of one object is not a pile either. You decide!
** Delete if empty--If selected, and if the PileOf object remains empty before shutdown, the PileOf object will be deleted. After all, an empty pile is not a pile. But then, a pile of one object is not a pile either. You decide!  


* A set of radio buttons for the way objects will be piled:
* A set of radio buttons for the way objects will be piled:
**Left to Right (this would be like a bookcase)
**Left to Right (this would be like a bookcase)
**Top to Bottom (more like a true pile)  
**Top to Bottom (more like a true pile)


Other PileOf settings pages/controls can be added as desired.
Other PileOf settings pages/controls can be added as desired.


To extract a list of all OS/2 public class objects, do the following:
To extract a list of all OS/2 public class objects, do the following:
* In the PILEOF.IDL file pass-through section:
* In the PILEOF.IDL file pass-through section:
<PRE>
<PRE>
Line 329: Line 190:
           }
           }
       }
       }
</PRE>
</PRE>


==Validating Drag/Drop
==Validating Drag/Drop==
 
Again, the behavior of the PileOf class demands that we restrict the user's ability to drop items into it. Only the objects from one of the classes selected in the PileOf settings page will be permitted into the pile.
Again, the behavior of the PileOf class demands that we restrict the user's ability to drop items into it. Only the objects from one of the classes selected in the PileOf settings page will be permitted into the pile.


Line 410: Line 269:


==PileOf Popup Menu Items==
==PileOf Popup Menu Items==
To limit the open view to one view (Details view), override wpFilterPopupMenu. Call the parent first and then do the following:
To limit the open view to one view (Details view), override wpFilterPopupMenu. Call the parent first and then do the following:
  /* Remove the tree/icon view menu option. Make sure delete is available */
  /* Remove the tree/icon view menu option. Make sure delete is available */
  return ( ( ulFlags | CTXT_DELETE ) & ~CTXT_TREE ~CTXT_ICON);
  return ( ( ulFlags | CTXT_DELETE ) & ~CTXT_TREE ~CTXT_ICON);
Details view is the default when you open a PileOf object. You can change to a new view or let the user specify a view by adding some extra code. Override wpModifyPopupMenu to add a few new options for the PileOf class, as follows:
Details view is the default when you open a PileOf object. You can change to a new view or let the user specify a view by adding some extra code. Override wpModifyPopupMenu to add a few new options for the PileOf class, as follows:
<PRE>
<PRE>
/* Get the module handle for the dll */
/* Get the module handle for the dll */
Line 434: Line 289:
                                       ,WPMENUID_PRIMARY);
                                       ,WPMENUID_PRIMARY);
</PRE>
</PRE>
To control what happens when one of the items being added is selected, override wpMenuItemSelected.  
To control what happens when one of the items being added is selected, override wpMenuItemSelected.


==Testing PILEOF.DLL==
==Testing PILEOF.DLL==
The makefile for this Workplace Shell class was designed to run on Intel machines. It uses the C Set compiler and the Developer's Toolkit for OS/2 Warp.
The makefile for this Workplace Shell class was designed to run on Intel machines. It uses the C Set compiler and the Developer's Toolkit for OS/2 Warp.


I created two files, INSTALL.EXE and UNINST.EXE, to test the PILEOF.DLL. INSTALL.EXE calls the following:
I created two files, INSTALL.EXE and UNINST.EXE, to test the PILEOF.DLL. INSTALL.EXE calls the following:
<PRE>
<PRE>
hab = WinInitialize ( 0 );
hab = WinInitialize (0);
/* register the PileOf class */
/* register the PileOf class */
fSuccess =
fSuccess =
Line 454: Line 308:
/* create an instance of the PileOf class */
/* create an instance of the PileOf class */
hobjPileOf = WinCreateObject ( "PileOf"
hobjPileOf = WinCreateObject ( "PileOf"
                                  , "PileOf..."
                              , "PileOf..."
                                  , "OBJECTID=<OBJECT_PILEOF>"
                              , "OBJECTID=<OBJECT_PILEOF>"
                                  , "<WP_DESKTOP>"
                              , "<WP_DESKTOP>"
                                  , CO_REPLACEIFEXISTS );
                              , CO_REPLACEIFEXISTS );
if ( hobjPileOf == 0 )
if ( hobjPileOf == 0 )
{
{
Line 478: Line 332:
   }
   }


   WinTerminate ( hab );
   WinTerminate (hab);
 
</PRE>
</PRE>


==Conclusion==
==Conclusion==
When developing your user interface, look closely at the world around you for ideas. Can you take advantage of OS/2's object technology to bring the behavior of your user interface closer to the way real objects behave? It may take some doing to verify that if an object looks like a hammer, it actually behaves like a hammer. But think how much easier you are making it for your customer. That is the final reward, and that is what really matters.
When developing your user interface, look closely at the world around you for ideas. Can you take advantage of OS/2's object technology to bring the behavior of your user interface closer to the way real objects behave? It may take some doing to verify that if an object looks like a hammer, it actually behaves like a hammer. But think how much easier you are making it for your customer. That is the final reward, and that is what really matters.


 
{{IBM-Reprint}}
 
[[Category:Developer Connection News Volume 8]][[Category:SOM Articles]]
'''Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation'''
 
 
[[Category:SOM Articles]]

Latest revision as of 00:00, 10 November 2022

by Bernie Arruza

Let's be creative and think about things in a new way. For instance, you know how objects in the world around you can be manipulated. Your fingers are like a form of user interface. You can pick things up and drop them. From experience, you have an idea of how much those things weigh (you adjust your muscles accordingly) or if they will break (from their composition).

Computers will someday be that smart, friendly, powerful, and three-dimensional. But we are not there yet.

With today's technology, OS/2 desktop objects represent a two-dimensional world fairly efficiently. Look at the objects you see on the OS/2 desktop; study their behavior. Can you think of new classes of objects? Can you think of new behaviors for those objects? Would these new behaviors enhance your desktop?

I receive a lot of magazines from different interest groups. What do I do with them? Well, some of them I read and throw away, but for the most part, when I read them I put them away in neatly arranged piles.

Unlike a folder, a pile "distinctively implies the laying of one thing...on top of another in a more or less orderly formation;...an assembly of like things or things of approximately the same size or shape" (from Webster's New Dictionary of Synonyms, Springfield, MA: GMerriam Co., 1973). The term pile is more adequate than heap, stack, mass, or bank to convey the idea behind this kind of behavior when we apply it to the OS/2 desktop.

This article discusses the Workplace Shell PileOf class, and provides sample code that demonstrates how you can quickly prototype the desired behavior of a Workplace Shell object.

Because the closest thing to a PileOf object is an OS/2 folder object, let's begin by looking at the differences between the two kinds of objects:

User's action A "regular" folder object A "regular" PileOf object
Drag and drop a folder from the desktop into a folder or PileOf object. Adds the new folder to its list of items.

If the folder object is closed, the folder is added at the end or according to a sorting criteria. If the folder holds other folders and it is opened, the new folder can be inserted between folders or placed inside another folder (its position can be modified by sorting criteria).

If the object is a "pile" of data files, or another non-folder class, the drop will not be allowed.

If the object is a "pile" of folders and the PileOf object is closed, the folder will go on top of the other folders. No other choices will be allowed. If the object is a "pile" of folders and the PileOf object is opened, the folder can be inserted in between folders or inside another folder (no sorting criteria is enforced for the folders in the pile).

Drag and drop a non-folder object from the desktop into a folder or PileOf object. Adds the new object to its list of items.

If the folder object is closed, the object is added at the end or according to sorting criteria. If the folder holds other objects and it is opened, the new object can be inserted between objects or placed inside another folder (its position can be modified by sorting criteria).

If the object is a "pile" of another object class or the object class being introduced is not in the set of permissible classes, the drop will fail.

If the object is a closed "pile" of objects of the same class as the object being introduced, or the object introduced is in the set of permissible classes, the object will go on top of the pile. No other choices will be allowed. If the object is an opened "pile" of objects of the same class as the object being introduced, or the object introduced is in the set of permissible classes, the object can be inserted between objects (no sorting criteria is enforced for the objects in the pile).

Drag two or more objects out of a folder or PileOf object and drop them on the desktop. All objects appear on the desktop. A new pile with those items is created on the desktop. Their order is maintained. The settings notebook should appear so you can name the pile.
Select sorting criteria for the PileOf piles object. Does not apply. Sorts the piles but not the contents of any of the piles.

Each pile maintains its own sort order.

Select sorting criteria. Destructive - All items in the folder are arranged according to sorting criteria. When the folder is closed or reopened, items will reflect sorting criteria. Non-destructive - All items in the pile can be arranged according to sorting criteria, but when you close the pile and reopen it, the original order is preserved.

You can drag and drop objects within the pile to arrange them the way you want. Also, a sort and save option can be included for larger piles.

Insert a PileOf object into a PileOf piles object. Does not apply. If the PileOf piles object is closed, the new pile goes on top. A dialog offering to change the name of the pile should appear.

If the PileOf piles object is opened, the new pile can be inserted between piles but not inside another pile.

Desktop area taken up by an opened folder object or PileOf object. Defaults to 2" x 7" (even if the folder contains only one object). Because objects appear as a list, which you can scroll down, the list can be made very small (for example, show only two objects).

Defaults to 1" x 3".

Resize the window so that it shows only two of the objects in the contained object. Some objects might become "hidden" because they are out of view, and the user can forget that the objects exist. No problem - the hidden objects can only belong to the classes supported by the PileOf object. You implicitly know what's there.

As you can see, the PileOf object class reuses a lot of the code from the WPFolder class. However, it looks and behaves differently.

Unlike a regular folder, the PileOf object:

  • Contains a settings page so the user can specify the type of pile and its behavior.
  • Validates drag/drop to ensure the object being dragged/dropped is the right type.
  • Contains extra items in its popup menu for the manipulation of its contents.

PileOf Settings Page

In the _wpAddSettingsPages method, call the parent first (WPFolder class) and then call the PileOf method:

/* Add PileOf settings page */
ulPageId = _AddPileOfPage(somSelf,hwndNotebook);

The _AddPileOfPage method fills up the PAGEINFO structure for the PileOf page and invokes the wpInsertSettingsPage method.

PAGEINFO pi;                               /* Variable declaration */

pi.cb                  = sizeof(PAGEINFO);
pi.hwndPage            = NULLHANDLE;
pi.usPageStyleFlags    = BKA_MAJOR;
pi.usPageInsertFlags   = BKA_FIRST;
pi.pfnwp               = MyDialogProc;     /* Pileof settings controls    */
                                           /* messages go here            */
pi.resid               = hmod;             /* from DosQueryModuleHandle of*/
                                           /* PILEOF.DLL                  */
pi.dlgid               = DLG_TITLE;
pi.pszName             = "PileOf";         /* PileOf tab text             */
pi.pCreateParams       = somSelf;          /* dialog create parms         */
pi.idDefaultHelpPanel  = 0;
pi.pszHelpLibraryName  = NULL;

ulPageID = _wpInsertSettingsPage ( somSelf, hwndNbk, &pi );

Note: You can/should override some of the wpAddFolderXXXXX (XXXXX=page type) methods and have them return SETTINGS_PAGE_REMOVED. It's up to you to decide what settings pages just plain don't belong for your PileOf object. The open view in my implementation (and the only view) is a modified Details view.

Figure 1. PileOf settings page and PileOf settings page with selected items

As you can see the settings page contains several controls:

  • A list box to display and choose from all the OS/2 system objects (you can choose one or more). If you choose to have a pile of bitmaps and icons, you select the Bitmap and Icon entries in the list box. Those are the only two classes of objects that you can drop into this PileOf object.
  • A set of check boxes for options:
    • One Class only - When checked, only one item can be selected from the list box (single selection). When unchecked, multiple items can be selected. After multiple items are selected, this button becomes disabled. To reactivate it, reduce the number of selected items in the list box to zero or one.
    • Spread contents - When checked, the popup menu for this PileOf object contains the Spread Contents menu item. When clicked, a folder/icon view of the contents of the pile is displayed.
    • Delete if empty - If selected, and if the PileOf object remains empty before shutdown, the PileOf object will be deleted. After all, an empty pile is not a pile. But then, a pile of one object is not a pile either. You decide!
  • A set of radio buttons for the way objects will be piled:
    • Left to Right (this would be like a bookcase)
    • Top to Bottom (more like a true pile)

Other PileOf settings pages/controls can be added as desired.

To extract a list of all OS/2 public class objects, do the following:

  • In the PILEOF.IDL file pass-through section:
    /* used in MyDialogProc */
    typedef  struct   _WINDATA
        {
             SOMObject   *somSelf;
             SOMObject   *somClassObj;
        } WINDATA, *PWINDATA;

    /* structure to keep track of PileOf class object list */
    /* there are several other ways of doing this !!!      */
    typedef  struct   _CLSINSERT1
        {
           PSZ            pszClass;
           SOMClass       *Class;
           SOMClass       *ClassParent;
           BOOL           flClassSelected;
        } CLSINSERT1, *PCLSINSERT1;

    /* PileOf instance data. Other info could/should be added */
    typedef struct _DATAPILEOF
        {
          ULONG           cClassIns;
          PCLSINSERT1 pClsInsert;
        } DATAPILEOF, *PDATAPILEOF;
  • In the source code file (PILEOF.C):
    /* Enumerate the object classes registered with workplace  */

    WinEnumObjectClasses(NULL,&ulSize);

    /* Initialize the structures */
    if (  ( pDtPileOf =
            (PDATAPILEOF)_wpAllocMem(somSelf, sizeof(DATAPILEOF),NULL) ) &&
          ( pObjClass = (POBJCLASS)_wpAllocMem(somSelf, ulSize,NULL) ) && 
            ( pClassIns = (PCLSINSERT1)_wpAllocMem(somSelf, ulSize,NULL) )
          )
       {
          memset((PBYTE)pClassIns,0,(USHORT)ulSize);
          pclsi = pClassIns;
          if ( WinEnumObjectClasses(pObjClass,&ulSize) )
          {
             poc = pObjClass;
             while (poc)
             {
                /* Find the NLS name for this class */
                ClassId   = SOM_IdFromString(poc->pszClassName);
                somPrintf( "The class name is: '%s'\n",poc->pszClassName);
                if ((Class =_somClassFromId(SOMClassMgrObject,ClassId)) &&
                    !(_wpclsQueryStyle(Class) & CLSSTYLE_PRIVATE))
                {
                    pszClass = _wpclsQueryTitle(Class);
                    if (!pszClass)
                       pszClass = poc->pszClassName;
                    somPrintf( "The private class name is: '%s'\n", pszClass);

                    /* Save the class in an entry in the CLSINSERT1 table that */
                    /* we construct, along with its parent class               */
                    pclsi->pszClass    = pszClass;
                    pclsi->Class       = Class;
                    pclsi->ClassParent = _somGetParent(Class);
                    pclsi->flClassSelected = FALSE;
                    pclsi     += 1;
                    cClassIns += 1;
                }
                SOMFree(ClassId);
                poc = poc->pNext;
             }
          }
       }

Validating Drag/Drop

Again, the behavior of the PileOf class demands that we restrict the user's ability to drop items into it. Only the objects from one of the classes selected in the PileOf settings page will be permitted into the pile.

To accomplish this, use the PileOf method ValidateDragAndDrop, which will know where the pile's instance data is, as follows:

/* Set pointer to PileOf data */
pDtPileOf = (PDATAPILEOF)_QueryPileOfInstData( somSelf );

/* Points to class list structure */
pClassIns  = pDtPileOf->pClsInsert;

/* Get the number of objects being dragged */
ulNumberOfObjects = DrgQueryDragitemCount( pdrgInfo);

/* Test each object */
for( ulCurrentObject = 0; ulCurrentObject<ulNumberOfObjects;
                                   ulCurrentObject++)
{
    pDragItem = DrgQueryDragitemPtr( pdrgInfo, ulCurrentObject);

    DrgQueryStrName( pDragItem->hstrRMF, sizeof( pszBuffer), pszBuffer);
    somPrintf( "The rendering mechanism is: '%s'\n", pszBuffer);

    /* Make sure that the rendering mechanism is DRM_OBJECT  */
    /* Only objects with a rendering mechanism of DRM_OBJECT */
    /* can be considered.                                    */
    if(DrgVerifyRMF( pDragItem, "DRM_OBJECT", NULL))
    {
      /* Get type of object */
      Object = OBJECT_FROM_DRAGITEM(pDragItem);

      /* Get class from object */
      somClassObj = _somGetClass ( Object );

      /* Get class title for this class */
      pszClass = _wpclsQueryTitle(somClassObj);

      /* See if this class title is in the list of classes in object's */
      /* instance data.                                                */
      for (j = 0; j < pDtPileOf->cClassIns; j++)
      {
        pclsi = pClassIns + j;

        if (pclsi->flClassSelected)

           /* See if class was selected for PileOf object */
           if (!strcmp(pclsi->pszClass, pszClass)) break;

        /* At least one of the objects being dragged is not in          */
        /* the list of allowed objects. DROP should fail !              */
        /* DESIGN: if one object in the DRAGINFO structure can          */
        /*         not be dropped in this PileOf object, can we somehow */
        /*         drop the rest? For now the DROP will fail for all.   */
        if ((j+1) == pDtPileOf->cClassIns)
           return (FALSE);

       }

      }
      else
       return ( FALSE );
   }

Next, override wpDragOver and wpDrop and call ValidateDragAndDrop, as follows:

/* Call the parent's method first   */
/* If the parent said it is okay to drop, then we will check it also. */

if( DOR_NEVERDROP != SHORT1FROMMR( mResult)){

        /* If the object is acceptable, return the mResult from the parent */
        if( FALSE == _ValidateDragAndDrop( somSelf, pdrgInfo))
            mResult = MRFROM2SHORT( DOR_NEVERDROP, DO_UNKNOWN);
}

PileOf Popup Menu Items

To limit the open view to one view (Details view), override wpFilterPopupMenu. Call the parent first and then do the following:

/* Remove the tree/icon view menu option. Make sure delete is available */
return ( ( ulFlags | CTXT_DELETE ) & ~CTXT_TREE ~CTXT_ICON);

Details view is the default when you open a PileOf object. You can change to a new view or let the user specify a view by adding some extra code. Override wpModifyPopupMenu to add a few new options for the PileOf class, as follows:

/* Get the module handle for the dll */
rc = DosQueryModuleHandle( "PILEOF.DLL", &hmod );

/* call the parent first */
fFlagsOut =   parent_wpModifyPopupMenu(somSelf,hwndMenu,hwndCnr,iPosition);

/* IDM_PRIMARYMENU is in my PILEOF.RC file. The items it represents  */
/* will be inserted at the end on WPMENUID_PRIMARY                   */
fSuccess = _wpInsertPopupMenuItems( somSelf
                                       ,hwndMenu
                                       ,iPosition
                                       ,hmod
                                       ,IDM_PRIMARYMENU
                                       ,WPMENUID_PRIMARY);

To control what happens when one of the items being added is selected, override wpMenuItemSelected.

Testing PILEOF.DLL

The makefile for this Workplace Shell class was designed to run on Intel machines. It uses the C Set compiler and the Developer's Toolkit for OS/2 Warp.

I created two files, INSTALL.EXE and UNINST.EXE, to test the PILEOF.DLL. INSTALL.EXE calls the following:

hab = WinInitialize (0);
/* register the PileOf class */
fSuccess =
        WinRegisterObjectClass ( "PileOf", "C:\\OS2\\DLL\\PILEOF.DLL" );

if ( fSuccess == FALSE )
{
        printf ( "Unable to register object class PileOf, error: " );
        printf ( "%x\n", ERRORIDERROR ( WinGetLastError ( hab ) ) );
}
/* create an instance of the PileOf class */
hobjPileOf = WinCreateObject ( "PileOf"
                               , "PileOf..."
                               , "OBJECTID=<OBJECT_PILEOF>"
                               , "<WP_DESKTOP>"
                               , CO_REPLACEIFEXISTS );
if ( hobjPileOf == 0 )
{
         printf ( "Unable to create PileOf... object, error: " );
         printf ( "%x\n", ERRORIDERROR ( WinGetLastError ( hab ) ) );
}

WinTerminate ( hab );

UNINST.EXE calls the following:

hab = WinInitialize ( 0 );

  fSuccess = WinDeregisterObjectClass ( "PileOf" );

  if ( fSuccess == FALSE )
  {
     printf ( "Unable to de-register object class PileOf, error: " );
     printf ( "%d\n", ERRORIDERROR ( WinGetLastError ( hab ) ) );
  }

  WinTerminate (hab);

Conclusion

When developing your user interface, look closely at the world around you for ideas. Can you take advantage of OS/2's object technology to bring the behavior of your user interface closer to the way real objects behave? It may take some doing to verify that if an object looks like a hammer, it actually behaves like a hammer. But think how much easier you are making it for your customer. That is the final reward, and that is what really matters.

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation