home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 18 / amigaformatcd18.iso / mui / mui_developer / c / examples / dragndrop.c < prev    next >
C/C++ Source or Header  |  1997-03-10  |  11KB  |  433 lines

  1. /*
  2. ** The Settings Demo shows how to load and save object contents.
  3. */
  4.  
  5. #include "demo.h"
  6.  
  7. static const char *nase[] =
  8. {
  9.     "Line  1",
  10.     "Line  2",
  11.     "Line  3",
  12.     "Line  4",
  13.     "Line  5",
  14.     "Line  6",
  15.     "Line  7",
  16.     "Line  8",
  17.     "Line  9",
  18.     "Line 10",
  19.     "Line 11",
  20.     "Line 12",
  21.     "Line 13",
  22.     "Line 14",
  23.     "Line 15",
  24.     "Line 16",
  25.     "Line 17",
  26.     "Line 18",
  27.     "Line 19",
  28.     "Line 20",
  29.     "Line 21",
  30.     "Line 22",
  31.     "Line 23",
  32.     "Line 24",
  33.     "Line 25",
  34.     "Line 26",
  35.     "Line 27",
  36.     "Line 28",
  37.     "Line 29",
  38.     "Line 30",
  39.     "Line 31",
  40.     "Line 32",
  41.     "Line 33",
  42.     "Line 34",
  43.     "Line 35",
  44.     "Line 36",
  45.     "Line 37",
  46.     "Line 38",
  47.     "Line 39",
  48.     "Line 40",
  49.     "Line 41",
  50.     "Line 42",
  51.     "Line 43",
  52.     "Line 44",
  53.     "Line 45",
  54.     "Line 46",
  55.     "Line 47",
  56.     "Line 48",
  57.     "Line 49",
  58.     "Line 50",
  59.      NULL,
  60. };
  61.  
  62.  
  63.  
  64. struct MUI_CustomClass *CL_FieldsList;
  65. struct MUI_CustomClass *CL_ChooseFields;
  66.  
  67.  
  68. ULONG __stdargs DoSuperNew(struct IClass *cl,Object *obj,ULONG tag1,...)
  69. {
  70.     return(DoSuperMethod(cl,obj,OM_NEW,&tag1,NULL));
  71. }
  72.  
  73.  
  74.  
  75. /****************************************************************************/
  76. /* FieldsList class                                                         */
  77. /****************************************************************************/
  78.  
  79. /*
  80. ** FieldsList list class creates a list that accepts D&D items
  81. ** from exactly one other listview, the one which is stored in
  82. ** the objects userdata. You could also store the allowed source
  83. ** object in another private attribute, I was just too lazy to add
  84. ** the get/set methods in this case. :-)
  85. **
  86. ** This class is designed to be used for both, the list of the
  87. ** available fields and the list of the visible fields.
  88. **
  89. ** Note: Stop being afraid of custom classes. This one here takes
  90. ** just a few lines of code, 90% of the stuff below is comments. :-)
  91. */
  92.  
  93.  
  94. struct FieldsList_Data
  95. {
  96.     LONG dummy;
  97. };
  98.  
  99.  
  100. ULONG FieldsList_DragQuery(struct IClass *cl,Object *obj,struct MUIP_DragDrop *msg)
  101. {
  102.     if (msg->obj==obj)
  103.     {
  104.         /*
  105.         ** If somebody tried to drag ourselves onto ourselves, we let our superclass
  106.         ** (the list class) handle the necessary actions. Depending on the state of
  107.         ** its MUIA_List_DragSortable attribute, it will either accept or refuse to become
  108.         ** the destination object.
  109.         */
  110.  
  111.         return(DoSuperMethodA(cl,obj,msg));
  112.     }
  113.     else if (msg->obj==(Object *)muiUserData(obj))
  114.     {
  115.         /*
  116.         ** If our predefined source object wants us to become active,
  117.         ** we politely accept it.
  118.         */
  119.  
  120.         return(MUIV_DragQuery_Accept);
  121.     }
  122.     else
  123.     {
  124.         /*
  125.         ** Otherwise, someone tried to feed us with something we don't like
  126.         ** very much. Just refuse it.
  127.         */
  128.  
  129.         return(MUIV_DragQuery_Refuse);
  130.     }
  131.  
  132. }
  133.  
  134.  
  135. ULONG FieldsList_DragDrop(struct IClass *cl,Object *obj,struct MUIP_DragDrop *msg)
  136. {
  137.     if (msg->obj==obj)
  138.     {
  139.         /*
  140.         ** user wants to move entries within our object, these kinds of actions
  141.         ** can get quite complicated, but fortunately, everything is automatically
  142.         ** handled by list class. We just need to pass through the method.
  143.         */
  144.  
  145.         return(DoSuperMethodA(cl,obj,msg));
  146.     }
  147.     else
  148.     {
  149.         /*
  150.         ** we can be sure that msg->obj is our predefined source object
  151.         ** since we wouldnt have accepted the MUIM_DragQuery and wouldnt
  152.         ** have become an active destination object otherwise.
  153.         */
  154.  
  155.         APTR entry;
  156.         LONG dropmark;
  157.         LONG sortable;
  158.  
  159.         /*
  160.         ** get the current entry from the source object, remove it there, and insert
  161.         ** it to ourselves. You would have to do a little more action if the source
  162.         ** listview would support multi select, but this one doesnt, so things get
  163.         ** quite easy. Note that this direct removing/adding of list entries is only
  164.         ** possible if both contain lists simple pointers to static items. If they would
  165.         ** feature custom construct/destruct hooks, we'd need to create a copy of
  166.         ** the entries instead of simply moving pointers.
  167.         */
  168.  
  169.         /* get source entry */
  170.         DoMethod(msg->obj,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&entry);
  171.  
  172.         /* remove source entry */
  173.         DoMethod(msg->obj,MUIM_List_Remove,MUIV_List_Remove_Active);
  174.  
  175.         get(obj,MUIA_List_DragSortable,&sortable);
  176.         if (sortable)
  177.         {
  178.             /*
  179.             ** if we are in a sortable list (in our case the visible fields),
  180.             ** we need to make sure to insert the new entry at the correct
  181.             ** position. The MUIA_List_DropMark attribute is maintained
  182.             ** by list class and shows us where we shall go after a drop.
  183.             */
  184.  
  185.             get(obj,MUIA_List_DropMark,&dropmark);
  186.             DoMethod(obj,MUIM_List_InsertSingle,entry,dropmark);
  187.         }
  188.         else
  189.         {
  190.             /*
  191.             ** we are about to return something to the available fields
  192.             ** listview which is always sorted.
  193.             */
  194.  
  195.             DoMethod(obj,MUIM_List_InsertSingle,entry,MUIV_List_Insert_Sorted);
  196.         }
  197.  
  198.         /*
  199.         ** make the insterted object the active and make the source listviews
  200.         ** active object inactive to give some more visual feedback to the user.
  201.         */
  202.  
  203.         get(obj,MUIA_List_InsertPosition,&dropmark);
  204.         set(obj,MUIA_List_Active,dropmark);
  205.         set(msg->obj,MUIA_List_Active,MUIV_List_Active_Off);
  206.  
  207.         return(0);
  208.     }
  209. }
  210.  
  211.  
  212. SAVEDS ASM ULONG FieldsList_Dispatcher(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
  213. {
  214.     switch (msg->MethodID)
  215.     {
  216.         case MUIM_DragQuery: return(FieldsList_DragQuery(cl,obj,(APTR)msg));
  217.         case MUIM_DragDrop : return(FieldsList_DragDrop (cl,obj,(APTR)msg));
  218.     }
  219.     return(DoSuperMethodA(cl,obj,msg));
  220. }
  221.  
  222.  
  223.  
  224. /****************************************************************************/
  225. /* ChooseFields class                                                       */
  226. /****************************************************************************/
  227.  
  228. /*
  229. ** This class creates two listviews, one contains all available fields,
  230. ** the other one contains the visible fields. You can control this
  231. ** stuff completely with D&D. This thing could e.g. be useful to
  232. ** configure the display of an address utility.
  233. */
  234.  
  235. static const char *fields[] =
  236. {
  237.     "Age",
  238.     "Birthday",
  239.     "c/o",
  240.     "City",
  241.     "Comment",
  242.     "Country",
  243.     "EMail",
  244.     "Fax",
  245.     "First name",
  246.     "Job",
  247.     "Name",
  248.     "Phone",
  249.     "Projects",
  250.     "Salutation",
  251.     "State",
  252.     "Street",
  253.     "ZIP",
  254.     NULL
  255. };
  256.  
  257. struct ChooseFields_Data
  258. {
  259.     LONG dummy;
  260. };
  261.  
  262. ULONG ChooseFields_New(struct IClass *cl,Object *obj,struct opSet *msg)
  263. {
  264.     Object *available, *visible;
  265.  
  266.     obj = (Object *)DoSuperNew(cl,obj,
  267.         MUIA_Group_Columns, 2,
  268.         MUIA_Group_VertSpacing, 1,
  269.         Child, TextObject, MUIA_Text_Contents, "\33cAvailable Fields\n(alpha sorted)", End,
  270.         Child, TextObject, MUIA_Text_Contents, "\33cVisible Fields\n(sortable)", End,
  271.         Child, ListviewObject,
  272.             MUIA_ControlChar, '1',
  273.             MUIA_Listview_DragType, 1,
  274.             MUIA_Listview_List, available = NewObject(CL_FieldsList->mcc_Class,NULL,
  275.                 InputListFrame,
  276.                 MUIA_List_SourceArray, (char **)fields,
  277.                 MUIA_List_ShowDropMarks, FALSE,
  278.                 TAG_DONE),
  279.             End,
  280.         Child, ListviewObject,
  281.             MUIA_Listview_DragType, 1,
  282.             MUIA_Listview_List, visible = NewObject(CL_FieldsList->mcc_Class,NULL,
  283.                 InputListFrame,
  284.                 MUIA_List_DragSortable, TRUE,
  285.                 TAG_DONE),
  286.             End,
  287.         End;
  288.  
  289.     if (obj)
  290.     {
  291.         /*
  292.         ** tell available object to accept items from visible object.
  293.         ** the use of MUIA_UserData is just to make the FieldsList
  294.         ** subclass more simple.
  295.         */
  296.  
  297.         set(available,MUIA_UserData,visible);
  298.  
  299.         /*
  300.         ** the other way round...
  301.         */
  302.  
  303.         set(visible,MUIA_UserData,available);
  304.     }
  305.  
  306.     return((ULONG)obj);
  307. }
  308.  
  309. SAVEDS ASM ULONG ChooseFields_Dispatcher(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
  310. {
  311.     switch (msg->MethodID)
  312.     {
  313.         case OM_NEW: return(ChooseFields_New(cl,obj,(APTR)msg));
  314.     }
  315.     return(DoSuperMethodA(cl,obj,msg));
  316. }
  317.  
  318.  
  319.  
  320. /****************************************************************************/
  321. /* Main Program                                                             */
  322. /****************************************************************************/
  323.  
  324.  
  325. VOID ExitClasses(VOID)
  326. {
  327.     if (CL_FieldsList  ) MUI_DeleteCustomClass(CL_FieldsList  );
  328.     if (CL_ChooseFields) MUI_DeleteCustomClass(CL_ChooseFields);
  329. }
  330.  
  331.  
  332. BOOL InitClasses(VOID)
  333. {
  334.     CL_FieldsList    = MUI_CreateCustomClass(NULL,MUIC_List ,NULL,sizeof(struct FieldsList_Data),FieldsList_Dispatcher);
  335.     CL_ChooseFields  = MUI_CreateCustomClass(NULL,MUIC_Group,NULL,sizeof(struct ChooseFields_Data ),ChooseFields_Dispatcher );
  336.  
  337.     if (CL_FieldsList && CL_ChooseFields)
  338.         return(TRUE);
  339.  
  340.     ExitClasses();
  341.     return(FALSE);
  342. }
  343.  
  344.  
  345. int main(int argc,char *argv[])
  346. {
  347.     Object *app,*window;
  348.  
  349.     init();
  350.  
  351.     if (!InitClasses())
  352.         fail(NULL,"failed to init classes.");
  353.  
  354.     app = ApplicationObject,
  355.         MUIA_Application_Title      , "DragnDrop",
  356.         MUIA_Application_Version    , "$VER: DragnDrop 19.5 (12.02.97)",
  357.         MUIA_Application_Copyright  , "©1992-95, Stefan Stuntz",
  358.         MUIA_Application_Author     , "Stefan Stuntz",
  359.         MUIA_Application_Description, "Demonstrate Drag & Drop capabilities",
  360.         MUIA_Application_Base       , "DRAGNDROP",
  361.  
  362.         SubWindow, window = WindowObject,
  363.             MUIA_Window_Title, "Drag&Drop Demo",
  364.             MUIA_Window_ID   , MAKE_ID('D','R','A','G'),
  365.             WindowContents, VGroup,
  366.  
  367.                 Child, NewObject(CL_ChooseFields->mcc_Class,NULL,TAG_DONE),
  368.  
  369.                 Child, ColGroup(2),
  370.                     Child, TextObject, TextFrame, MUIA_Background, MUII_TextBack, MUIA_Text_Contents, "\33cListview without\nmultiple selection.", End,
  371.                     Child, TextObject, TextFrame, MUIA_Background, MUII_TextBack, MUIA_Text_Contents, "\33cListview with\nmultiple selection.", End,
  372.                     Child, ListviewObject,
  373.                         MUIA_Listview_DragType, 1,
  374.                         MUIA_Dropable, FALSE,
  375.                         MUIA_Listview_List, ListObject,
  376.                             InputListFrame,
  377.                             MUIA_List_SourceArray, nase,
  378.                             MUIA_List_DragSortable, TRUE,
  379.                             End,
  380.                         End,
  381.                     Child, ListviewObject,
  382.                         MUIA_Dropable, TRUE,
  383.                         MUIA_Listview_DragType, 1,
  384.                         MUIA_Listview_MultiSelect, MUIV_Listview_MultiSelect_Default,
  385.                         MUIA_Listview_List, ListObject,
  386.                             InputListFrame,
  387.                             MUIA_List_SourceArray, nase,
  388.                             MUIA_List_DragSortable, TRUE,
  389.                             End,
  390.                         End,
  391.                     End,
  392.                 End,
  393.             End,
  394.         End;
  395.  
  396.     if (!app)
  397.         fail(app,"Failed to create Application.");
  398.  
  399.  
  400.     DoMethod(window,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
  401.         app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
  402.  
  403.  
  404.     /*
  405.     ** This is the ideal input loop for an object oriented MUI application.
  406.     ** Everything is encapsulated in classes, no return ids need to be used,
  407.     ** we just check if the program shall terminate.
  408.     ** Note that MUIM_Application_NewInput expects sigs to contain the result
  409.     ** from Wait() (or 0). This makes the input loop significantly faster.
  410.     */
  411.  
  412.     set(window,MUIA_Window_Open,TRUE);
  413.  
  414.     {
  415.         ULONG sigs = 0;
  416.  
  417.         while (DoMethod(app,MUIM_Application_NewInput,&sigs) != MUIV_Application_ReturnID_Quit)
  418.         {
  419.             if (sigs)
  420.             {
  421.                 sigs = Wait(sigs | SIGBREAKF_CTRL_C);
  422.                 if (sigs & SIGBREAKF_CTRL_C) break;
  423.             }
  424.         }
  425.     }
  426.  
  427.     set(window,MUIA_Window_Open,FALSE);
  428.  
  429.     MUI_DisposeObject(app); /* note that you must first dispose all objects */
  430.     ExitClasses();          /* *before* deleting the classes! */
  431.     fail(NULL,NULL);
  432. }
  433.