home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / boopsi / dragclass / source / drag.class < prev    next >
Text File  |  1977-12-31  |  23KB  |  802 lines

  1. ////
  2. ////  ATTN! This Class needs animtools from "RKM Libraries"
  3. ////        since that package is (c) by CBM, U must get
  4. ////        somewhere else ...
  5. ////
  6.  
  7. //
  8. // 17-04-94
  9. //  es laeuft nun anscheinend alles, beginne nun mit dem cleanup
  10. // oha -  etwas klappt noch nicht (bzw. nicht mehr...):
  11. //  2x Selection eines Gadgets laesst es in der Falschen Farbe rendern ...
  12. //
  13. // Brauche bringend ein Threshold ...
  14. //  - Chris mag es nicht ... naja sowas gehoert in Prefs ...
  15. //
  16.  
  17. PRIVATE_DEFINES // intern, steuerung der codegeneration
  18. //      TEST      1
  19. //      MYDEBUG 1
  20.  
  21.  
  22. CLASS        drag
  23. SUPERCLASS  "gadgetclass",NULL
  24.  
  25. ////////////////////////////////////////
  26.  
  27. FIRST_ATTR_NUM TAG_USER+1728
  28. FIRST_METH_NUM        1728
  29.  
  30. INCLUDES // extern sichtbar
  31.     <intuition/gadgetclass.h>
  32.     <intuition/cghooks.h>
  33.  
  34. PRIVATE_INCLUDES // intern
  35.     "animtools.h"
  36. //      "animtools_proto.h"
  37.     <string.h>
  38.     <graphics/gels.h>
  39.     <lists.h>
  40.     <clib/macros.h>
  41.  
  42. LIBRARIES
  43.     exec
  44.     intuition
  45.     utility
  46.     graphics
  47.     layers
  48.  
  49. ////////////////////////////////////////
  50.  
  51. DEFINES // extern sichtbar
  52.     DRAGNAME "draggclass"
  53.  
  54. PRIVATE_DEFINES // intern
  55.  
  56.     IEQUALIFIER_ANYSHIFT    (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
  57.  
  58.     BORDER_WIDTH        4
  59.     BORDER_HEIGHT        4
  60.     THRESHOLD_X        4
  61.     THRESHOLD_Y        4
  62.  
  63.     // INSTANCE FLAGS
  64.     FIX_WIDTH        (1 << 0) // Gadget cannot modify its Width according to Image
  65.     FIX_HEIGHT        (1 << 1) // Gadget cannot modify its Height according to Image
  66. //    VISIBLE         (1 << 2) // Gadget BOB is Visible
  67.     SELECTED        (1 << 3) // Gadget is Selected (almost identical to GadgetFlag)
  68.     SUPPRESS_REDRAW     (1 << 4) // Gadget cannot be rendered now
  69.     FREE_PLACEMENT        (1 << 5) // Gadget can be placed everywhere in the current Window (IE Left & Top are not Fixed)
  70.     FREE_WINDOW        (1 << 6) // Gadget can be moved to another Window -- unused for now ...
  71.     NEWPOS            (1 << 7)
  72.  
  73.  
  74.     GADOB     ((struct Gadget *)o)
  75.     NBOB     inst->newbob
  76.     TBOB     inst->act_bob
  77.     GDATA     inst->gdata
  78.     GGI     inst->gdata->ginfo
  79.     GRP     (&inst->gdata->rp)
  80.     GVP     (&inst->gdata->screen->ViewPort)
  81.  
  82.     _DO  do{
  83.     _OD  }while(0)
  84.  
  85.     IS_SELECTED        (inst->flags & SELECTED)
  86.     MARK_SELECTED()         _DO inst->flags |=  SELECTED; GADOB->Flags |=  GFLG_SELECTED; _OD
  87.     MARK_UNSELECTED()       _DO inst->flags &= ~SELECTED; GADOB->Flags &= ~GFLG_SELECTED; _OD
  88.  
  89.     IS_VISIBLE        (inst->is_shown)
  90.     MAKE_INVISIBLE()        _DO inst->is_shown = 0; RemBob (TBOB);      _OD
  91.     MAKE_VISIBLE()          _DO inst->is_shown = 1; AddBob (TBOB, GRP); _OD
  92.  
  93.     INIT_GELS()             if (NULL == (GGI  = setupGelSys(GRP, 0x03))) { return GMR_NOREUSE; } else /* if */
  94.     MAKE_BOB()              if (NULL == (TBOB = makeBob(NBOB))) {          return GMR_NOREUSE; } else /* if */
  95.     KILL_BOB()              _DO if (TBOB)      freeBob      (TBOB, NBOB->nb_RasDepth); TBOB = NULL; _OD
  96.     EXIT_GELS(gd)           _DO if (gd->ginfo) cleanupGelSys(gd->ginfo, &gd->rp); gd->ginfo = NULL; _OD
  97.  
  98.     RECALC_WIDTH()          GADOB->Width = 2*BORDER_WIDTH + NBOB->nb_WordWidth*16;
  99.     RECALC_HEIGHT()         GADOB->Height= 2*BORDER_HEIGHT+ NBOB->nb_LineHeight;
  100.     RECALC_SIZES()          if (!(inst->flags & FIX_WIDTH)) RECALC_WIDTH(); if (!(inst->flags & FIX_HEIGHT)) RECALC_HEIGHT();
  101.  
  102.     SHOW_GELS(gd)           _DO SortGList (&((gd)->rp)); DrawGList (&((gd)->rp), &((gd)->screen->ViewPort)); WaitTOF (); _OD
  103.  
  104.     RENDER()                do_render  (o, (struct gpRender *)msg, inst)
  105.     DESELECT()              do_deselect(o, (Msg)msg, inst)
  106.     SELECT()                do_select  (o, (Msg)msg, inst)
  107.  
  108.         HIDE_ALL_BOBS()     do_hide_all    (GDATA)
  109.     REL_MOVE_ALL_BOBS(x,y)  do_move_all    (GDATA,x,y)
  110.         SHOW_ALL_BOBS()     do_show_all    (GDATA)
  111.     DESELECT_ALL_BOBS()     do_deselect_all(GDATA)
  112.  
  113.     TRY_TO_DROP()           _DO DQ(bug("*** DROPPING ***\n")); DisplayBeep(NULL); _OD
  114.     TRY_TO_DBLCLICK()       _DO DQ(bug("*** DBLCLICK ***\n")); DisplayBeep(NULL); _OD
  115.  
  116.     Forbid()
  117.     Permit()
  118.     LockLayers(li)
  119.     UnlockLayers(li)
  120.  
  121. ////////////////////////////////////////
  122.  
  123. CONTENTS // internal
  124.     struct MinNode     act_node;  // used to keep track of all selected drag-elements
  125.     Object        *act_self;  // needed to get the Objectinfo from the act_node
  126.     struct Bob    *act_bob;   // temp bob
  127.  
  128.     BYTE         is_shown;  // temp bob is visible
  129.     BYTE         is_selected;// similar to GADOB->Flags & SELECTED
  130.     UWORD         flags;     // padding flags
  131.  
  132.     struct newBob    *newbob;    // attribute render-data
  133.     struct GlobalData*gdata;    // a shortcut to cl->cl_Dispatcher.h_SubEntry
  134.     struct Window    *window;    // ... no alternative
  135.     struct timeval     lastclick; // to check a doubleclick
  136.  
  137. ////////////////////////////////////////////////////////////
  138. //
  139. //    Entry/Exit Code  for Instances
  140. //            (no En/Ex - Code for Class needed)
  141. //
  142. ////////////////////////////////////////////////////////////
  143.  
  144. OBJ_INIT    // to be: OM_NEW
  145.     inst->act_self    = o;
  146.     MARK_UNSELECTED();
  147.  
  148. OBJ_EXIT    // to be: OM_DISPOSE
  149.     DESELECT();
  150.  
  151.  
  152. ////////////////////////////////////////////////////////////
  153. //
  154. //  SUPPORT STRUCTURES
  155. //
  156. ////////////////////////////////////////////////////////////
  157.  
  158. STRUCTURES //external
  159.  
  160. ////////////////////////////////////////
  161. //
  162. //  Dies werden voraussichtlich "KompatibiliatesStrukturen"
  163. //  sie sind abhaengig von Bildschirm und von Art der
  164. //  Objecte;
  165. //  zB sei eine Subclass "IconClass" gegeben
  166. //  auf dem gleichen Bildschirm ausserdem noch eine Application
  167. //  die ebenfalls Dragobjecte verwendet, aber inkompatibel ist
  168. //  zu den Icons (zB ein GUIBuilder)
  169. //  wie verhindere ich nun, dass die Selektionen der Applikation
  170. //  mit denen der WB in einen Top geworfen werden ? - eben durch
  171. //  diese Struktur; alle Objecte, die solch eine STruktur teilen,
  172. //  koennen gemeinsam gebewgt werden, Shift-selectet werden, und
  173. //  sie deselectieren einander bei normaler Selection (ohne Shift)
  174. //  da es zB in einer Wb noch unterklassen von Icons geben kann,
  175. //  (was passiert wenn ich etwas auf ein anderes Volume schiebe,
  176. //  anstatt nur im akuellen Volume? wenn ich ein Volume auf ein
  177. //  anderes ziehe, dazu noch appicons ...)
  178. //  ist diese Teststruktur noch bei weitem nicht ausreichend;
  179. //  ich werde sie jedoch fuer diesen Protoypen nicht weiter ausbauen,
  180. //  schliesslich handelt es sich ja nur um eine "Studie"
  181. //
  182.  
  183. struct GlobalData {
  184.     int         num_selected;
  185.     struct MinList  list;  // all selected drag-objects
  186.     struct MinList  dests; // all registered drop-targets (a tree might be better)
  187.     struct GelInfo* ginfo; // once mor: all selected objects - here: their bobs
  188.     int         is_shown; // ginfo is (not) empty
  189.     ULONG        id; // future
  190.     struct Screen*  screen;
  191.     struct RastPort rp;     // copy of screen-rp
  192.  
  193.     // --- the following entries are to manage DoubleClicks
  194.     struct timeval  last_selection;
  195.     Object       *last_selected;
  196.  
  197.     // --- we keep track of all movements in order to be able to move all
  198.     //       dragged gadgets - if possible
  199.     WORD move_X, move_Y;
  200. }; /* struct GlobalData */
  201.  
  202.  
  203.  
  204. ////////////////////////////////////////////////////////////
  205. //
  206. //  SUPPORT DATA AND FUNCTIONS
  207. //
  208. ////////////////////////////////////////////////////////////
  209.  
  210. SUPPORT // internal
  211.  
  212. ////////////////////////////////////////
  213. //
  214. //  ARRRRRRGHHHHHh ......
  215. //  Global Data ...
  216. //
  217. ////////////////////////////////////////
  218.  
  219. #ifdef Threshold
  220. static int dist_X, dist_Y;
  221. #endif
  222.  
  223. ////////////////////////////////////////
  224.  
  225. static void do_clear (Object *o, struct gpRender *msg, struct _CLASS *inst) {
  226. } /* do_clear */
  227.  
  228.  
  229.  
  230.  
  231. static void do_render(Object *o, struct gpRender *msg, struct _CLASS *inst) {
  232.     struct RastPort *rp;
  233.  
  234.  DQ(bug("  RENDER\n"));
  235.  
  236.     if (inst->flags & SUPPRESS_REDRAW)
  237.     return;
  238.  
  239.     if (msg->MethodID != GM_RENDER) {
  240.     if (!(msg->gpr_GInfo))
  241.         return;
  242.  
  243.     rp = ObtainGIRPort(msg->gpr_GInfo);
  244.     } else {
  245.     rp = msg->gpr_RPort;
  246.     } /* if */
  247.  
  248.     if (rp) {
  249.     UWORD back, shine, shadow;
  250.     UWORD *pens = msg->gpr_GInfo->gi_DrInfo->dri_Pens;
  251.  
  252.     if (!(IS_SELECTED)) { // If the gadget is selected, reverse the meanings of the pens
  253.         back   = pens[BACKGROUNDPEN];
  254.         shine  = pens[     SHINEPEN];
  255.         shadow = pens[    SHADOWPEN];
  256.     } else {
  257.         back   = pens[  FILLPEN];
  258.         shine  = pens[SHADOWPEN];
  259.         shadow = pens[ SHINEPEN];
  260.     } /* if */
  261.  
  262.     if (inst->flags & NEWPOS) { // --- Fully Erase the old gadget.
  263.         inst->flags &= ~ NEWPOS;
  264.         if (inst->flags & FREE_PLACEMENT) {
  265.         SetDrMd(rp, JAM1);
  266.         SetAPen(rp, pens[BACKGROUNDPEN]);
  267.         RectFill(rp, GADOB->LeftEdge,
  268.                  GADOB->TopEdge,
  269.                  GADOB->LeftEdge + GADOB->Width,
  270.                  GADOB->TopEdge  + GADOB->Height);
  271.         GADOB->TopEdge    += GDATA->move_Y;
  272.         GADOB->LeftEdge += GDATA->move_X;
  273.         } /* if */
  274.         // wir muessten nun noch einmal die ganze Liste
  275.         // durchgehen und alle gadgets neuzeichnen ...
  276.     } else {
  277.         SetDrMd(rp, JAM1);
  278.         SetAPen(rp, back);     // Erase the old gadget.
  279.         RectFill(rp, GADOB->LeftEdge,
  280.              GADOB->TopEdge,
  281.              GADOB->LeftEdge + GADOB->Width,
  282.              GADOB->TopEdge  + GADOB->Height);
  283.  
  284.         SetAPen(rp, shadow);   // Draw shadow edge.
  285.         Move(rp, GADOB->LeftEdge + 1, GADOB->TopEdge + GADOB->Height);
  286.         Draw(rp, GADOB->LeftEdge + GADOB->Width, GADOB->TopEdge + GADOB->Height);
  287.         Draw(rp, GADOB->LeftEdge + GADOB->Width, GADOB->TopEdge + 1);
  288.  
  289.         SetAPen(rp, shine);    // Draw shine edge.
  290.         Move(rp, GADOB->LeftEdge, GADOB->TopEdge + GADOB->Height - 1);
  291.         Draw(rp, GADOB->LeftEdge, GADOB->TopEdge);
  292.         Draw(rp, GADOB->LeftEdge + GADOB->Width - 1, GADOB->TopEdge);
  293.  
  294.         if (NBOB) {
  295.         struct Image im={ 0,0,                // left&top
  296.                   NBOB->nb_WordWidth*16,    // wid
  297.                   NBOB->nb_LineHeight,        // hig
  298.                   NBOB->nb_RasDepth,        // dep
  299.                   NBOB->nb_Image,        // imda
  300.                   NBOB->nb_PlanePick,        // ppck
  301.                   NBOB->nb_PlaneOnOff,        // poo
  302.                   NULL };            // next
  303.  
  304.         DrawImage(rp, &im, GADOB->LeftEdge + BORDER_WIDTH, GADOB->TopEdge + BORDER_HEIGHT);
  305.         } /* if  nbob */
  306.     } /* if dodraw */
  307.     } /* if rp */
  308.  
  309.     if (msg->MethodID != GM_RENDER) {
  310.     ReleaseGIRPort(rp);
  311.     } /* if */
  312.  
  313. } /* do_render */
  314.  
  315. ////////////////////////////////////////
  316.  
  317. static int do_select (Object *o, Msg msg, struct _CLASS *inst) {
  318.  
  319.  DQ(bug("select_self ...\n"));
  320.  
  321.     if (!(IS_SELECTED)) {
  322.     MARK_SELECTED();
  323.  
  324.     MAKE_BOB();
  325.  
  326.     if (GDATA) {
  327.         Forbid();
  328.         GDATA->num_selected ++;
  329.         AddTail((struct List*)&GDATA->list, (struct Node *)&inst->act_node);
  330.         Permit();
  331.     } /* if */
  332.     } /* if */
  333.  
  334.     return GMR_MEACTIVE;
  335. } /* do_select */
  336.  
  337. ////////////////////////////////////////
  338.  
  339. static void do_deselect (Object *o, Msg msg, struct _CLASS *inst) {
  340.  
  341.  DQ(bug("DEselect_self ...\n"));
  342.  
  343.     if (IS_SELECTED) {
  344.     MARK_UNSELECTED();
  345.  
  346.     if (IS_VISIBLE) {
  347.         MAKE_INVISIBLE();
  348.         if (GDATA)
  349.         SHOW_GELS(GDATA);
  350.     } /* if */
  351.  
  352.     if (GDATA) {
  353.  
  354.         Forbid();
  355.         Remove ((struct Node *)&inst->act_node);
  356.         GDATA->num_selected --;
  357.         Permit();
  358.  
  359.         if (GDATA->num_selected == 0) {
  360.         // ---- Nota Bene INIT/EXIT-GELS should better be put into CLASS_INIT/EXIT
  361.         //    but we do not have any Information 'bout Screens there;
  362.         //    worse - using MUI [;)] we do not have a permanent Screen.
  363.         EXIT_GELS(GDATA);
  364.         } /* if */
  365.     } /* if */
  366.  
  367.     KILL_BOB();
  368.     } /* if */
  369. } /* do_deselect */
  370.  
  371. ////////////////////////////////////////
  372.  
  373. //////////////////////////////////////////////////
  374. //
  375. //  WARNING!
  376. //
  377. //  the following routines are quite time-expensive,
  378. //  though they are called from within InputDevice;
  379. //  Sorry, but I do not know any workaround for that
  380. //  (ok, we could use GadTools way, but that's no
  381. //  Solution for a BOOPSI Object)
  382. //
  383. //////////////////////////////////////////////////
  384.  
  385. #define o inst->act_self
  386.  
  387. static void do_hide_all (struct GlobalData *gd) {
  388.     struct _CLASS *inst;
  389.  
  390.  DQ(bug("hide_all\n"));
  391.  
  392.     if (gd && gd->ginfo) {
  393.     Forbid();
  394.     for (inst = GetHead(&gd->list); inst; inst = GetSucc(inst)) {
  395.         MAKE_INVISIBLE();
  396.     } /* for */
  397.     Permit();
  398.  
  399.     SHOW_GELS(gd);
  400.     EXIT_GELS(gd);
  401.     } /* if */
  402. } /* do_hide_all */
  403.  
  404. ////////////////////////////////////////
  405.  
  406. static int do_show_all (struct GlobalData *gd) {
  407.     struct _CLASS *inst;
  408.  
  409.  DQ(bug("show_all\n"));
  410.  
  411.     if (!gd)
  412.     return GMR_NOREUSE;
  413.  
  414.     if (gd->num_selected > 0) {
  415.     if (!(gd->ginfo)) {
  416.         if (NULL == (gd->ginfo  = setupGelSys(&gd->rp, 0x03))) {
  417.         return GMR_NOREUSE;
  418.         } /* if */
  419.     } /* if */
  420.  
  421.     for (inst = GetHead(&gd->list); inst; inst = GetSucc(inst)) {
  422.         TBOB->BobVSprite->X  = inst->window->LeftEdge + GADOB->LeftEdge + BORDER_WIDTH;
  423.         TBOB->BobVSprite->Y  = inst->window->TopEdge  + GADOB->TopEdge  + BORDER_HEIGHT;
  424.         MAKE_VISIBLE();
  425.     } /* while */
  426.  
  427. // --- Immediately after ShowAll we are calling MoveAll, so there is no need
  428. //     to draw'em now; insted I'd rather only sort our gelslist here, and
  429. //     drop gelssorting in my other calls.
  430. //      SHOW_GELS(gd);
  431.     } /* if */
  432.     return GMR_MEACTIVE;
  433. } /* do_show_all */
  434.  
  435. ////////////////////////////////////////
  436.  
  437. static void do_move_all (struct GlobalData *gd, int x, int y) {
  438.     struct _CLASS *inst;
  439.  DQ(bug("move_all\n"));
  440.     if (gd && gd->ginfo) {
  441.     for (inst = GetHead(&gd->list); inst; inst = GetSucc(inst)) {
  442.         TBOB->BobVSprite->X +=x;
  443.         TBOB->BobVSprite->Y +=y;
  444.     } /* for */
  445.  
  446.     SHOW_GELS(gd);
  447.     } /* if */
  448. } /* do_move_all */
  449.  
  450. ////////////////////////////////////////
  451.  
  452. static void do_deselect_all (struct GlobalData *gd) {
  453.     struct _CLASS *inst;
  454.  
  455.  DQ(bug("deselect_all\n"));
  456.     if (gd && (gd->num_selected > 0)) {
  457.     do_hide_all(gd);
  458.  
  459.     for (inst = GetHead(&gd->list); inst;) {
  460.         APTR next;
  461.         struct TagItem tags[2] = { GA_Selected, 0, TAG_DONE };
  462.         next = GetSucc(inst);
  463. //          freeBob       (TBOB, NBOB->nb_RasDepth);
  464. //          TBOB = NULL;
  465. // SetGadgetAttrs  ((struct Gadget *)inst->act_self, inst->window, NULL, GA_Selected, FALSE, TAG_DONE);
  466.         SetGadgetAttrsA ((struct Gadget *)inst->act_self, inst->window, NULL, tags);
  467.         RefreshGList    ((struct Gadget *)inst->act_self, inst->window, NULL, 1);
  468.         inst = next;
  469.     } /* for */
  470.     } /* if */
  471. } /* do_deselect_all */
  472.  
  473. #undef o
  474.  
  475.  
  476. ////////////////////////////////////////
  477.  
  478. ////////////////////////////////////////////////////////////
  479. //
  480. // NEW OR CHANGED ATTRIBUTES
  481. //
  482. ////////////////////////////////////////////////////////////
  483.  
  484. ATTRIBUTE GDA_NewBob
  485.     $I NBOB = (APTR)val; RECALC_SIZES();
  486.     $G val    = (ULONG)NBOB;
  487.     $S if (!IS_SELECTED) NBOB = (APTR)val; else { DESELECT(); NBOB = (APTR)val; SELECT(); } RECALC_SIZES(); retval = 1;
  488.  
  489. ATTRIBUTE GA_Selected
  490.     $S if ((val) && !(IS_SELECTED)) { SELECT(); retval = 1; } else if ((!val) && (IS_SELECTED)) { DESELECT(); retval = 1; }
  491.     $U if ((val) && (!IS_SELECTED)) { SELECT();             } else if ((!val) && (IS_SELECTED)) { DESELECT(); }
  492.  
  493. ATTRIBUTE GDA_GData
  494.     $I GDATA = (APTR)val;
  495.     $G val     = (ULONG)GDATA;
  496.  
  497. ATTRIBUTE GDA_FreePlacement // object is moveable on the Window
  498.     $I if (val) inst->flags |= FREE_PLACEMENT; else inst->flags &= ~FREE_PLACEMENT;
  499.     $G val = (inst->flags & FREE_PLACEMENT) ? 1 : 0;
  500.  
  501. ATTRIBUTE GDA_NewPlacement // move, if You are free placeable
  502.     $S inst->flags |= NEWPOS; retval = 1;
  503.  
  504. ATTRIBUTE GA_Width
  505.     $I if (val) inst->flags |= FIX_WIDTH;  else { inst->flags &= ~FIX_WIDTH;  RECALC_WIDTH();  }
  506.     $S if (val) inst->flags |= FIX_WIDTH;  else { inst->flags &= ~FIX_WIDTH;  RECALC_WIDTH();  } retval = 1;
  507.  
  508. ATTRIBUTE GA_Height
  509.     $I if (val) inst->flags |= FIX_HEIGHT; else { inst->flags &= ~FIX_HEIGHT; RECALC_HEIGHT(); }
  510.     $S if (val) inst->flags |= FIX_HEIGHT; else { inst->flags &= ~FIX_HEIGHT; RECALC_HEIGHT(); } retval = 1;
  511.  
  512.  
  513.  
  514. // GFLG_REL-RIGHT/BOTTOM in fact cannot be set;
  515. // we do just try to make sure here, they can't be set
  516. // in the basic gadget structure by resetting them as
  517. // soon as they are set ...
  518. ATTRIBUTE    GA_RelRight
  519.     $I GADOB->Flags &= ~GFLG_RELRIGHT;
  520.     $S GADOB->Flags &= ~GFLG_RELRIGHT;
  521. ATTRIBUTE    GA_RelBottom
  522.     $I GADOB->Flags &= ~GFLG_RELBOTTOM;
  523.     $S GADOB->Flags &= ~GFLG_RELBOTTOM;
  524.  
  525.  
  526. ////////////////////////////////////////////////////////////
  527. //
  528. // NEW OR CHANGED METHODS
  529. //
  530. ////////////////////////////////////////////////////////////
  531.  
  532. METHOD GM_HITTEST struct gpHitTest*
  533.  
  534.     return GMR_GADGETHIT;
  535.  
  536. ////////////////////////////////////////
  537.  
  538. METHOD GM_RENDER struct gpRender*
  539.  
  540.     RENDER();
  541.     return 1;
  542.  
  543. ////////////////////////////////////////
  544.  
  545. METHOD GM_GOINACTIVE struct gpGoInactive*
  546.  
  547.     if (GDATA) {
  548.         HIDE_ALL_BOBS();
  549.         UnlockLayers(&GDATA->screen->LayerInfo);
  550.     } /* if */
  551.  
  552.     return 1;
  553.  
  554. ////////////////////////////////////////
  555.  
  556. METHOD GM_GOACTIVE struct gpInput*
  557.     ULONG retval;
  558.     struct InputEvent *ie;
  559.  
  560.     if (ie = msg->gpi_IEvent) { // only act on direct user-input
  561.         int inter;
  562.  
  563.         if (!GDATA) {
  564.         if (!IS_SELECTED) {
  565.             MARK_SELECTED();
  566.             RENDER();
  567.         } /* if */
  568.         return GMR_NOREUSE;
  569.         } /* if */
  570.  
  571.         // --- solange wir nix besseres wissen ...
  572.         inst->window  = msg->gpi_GInfo->gi_Window;
  573.         GDATA->screen = msg->gpi_GInfo->gi_Screen;
  574.         *GRP      = GDATA->screen->RastPort;
  575.         LockLayers(&GDATA->screen->LayerInfo);
  576.         GDATA->move_X = 0;
  577.         GDATA->move_Y = 0;
  578. #ifdef Threshold
  579.         dist_X = dist_Y = 0;
  580. #endif
  581.  
  582.         // --- I think, it is not necessary to free/reallocate/rerender our own data, if we are already selected
  583.         if ((inter = IS_SELECTED)) {
  584.         MARK_UNSELECTED();
  585.         inst->flags |= SUPPRESS_REDRAW;
  586.         } /* if */
  587.  
  588.         if (!(ie->ie_Qualifier & IEQUALIFIER_ANYSHIFT)) {
  589.         DESELECT_ALL_BOBS();
  590.         } /* if */
  591.  
  592.         if (inter) {
  593.         MARK_SELECTED();
  594.         inst->flags &= ~SUPPRESS_REDRAW;
  595.         } else {
  596.         SELECT();
  597.         RENDER();
  598.         } /* if */
  599.  
  600.         // --- Check for Doubleclick; putting it into HANDLEINPUT
  601.         //       would decrease speed, since the flag is checked on
  602.         //        every IEvent, so we have to put it here 8-(
  603.         if (o == GDATA->last_selected) {
  604.         if (DoubleClick(GDATA->last_selection.tv_secs, GDATA->last_selection.tv_micro, ie->ie_TimeStamp.tv_secs, ie->ie_TimeStamp.tv_micro )) {
  605.             GDATA->last_selected = NULL;
  606.  
  607.             TRY_TO_DBLCLICK();
  608.  
  609.             return GMR_NOREUSE;
  610.         } /* if */
  611.         } /* if */
  612.         GDATA->last_selected  = o;
  613.         GDATA->last_selection = ie->ie_TimeStamp;
  614.  
  615.         return GMR_MEACTIVE;
  616.     } else {
  617.         return GMR_NOREUSE;
  618.     } /* if */
  619.     return retval;
  620.  
  621. ////////////////////////////////////////
  622.  
  623. METHOD GM_HANDLEINPUT struct gpInput*
  624.     ULONG retval = GMR_MEACTIVE;
  625.     struct InputEvent *ie = msg->gpi_IEvent;
  626.  
  627. // extern char *class_name    (ULONG);
  628. // DQ(bug(" gpinfo: gi=%08lx ie=$%08lx te=$%08lx->%ld ms=(%3ld,%3ld)\n", msg->gpi_GInfo, ie, msg->gpi_Termination, *(msg->gpi_Termination), msg->gpi_Mouse.X, msg->gpi_Mouse.Y));
  629. // DQ(bug(" ie:  cl=$%02lx sc=$%02lx cd=$%04lx ql=$%04lx ea=$%08lx tv=(%d.%010ld)\n", ie->ie_Class, ie->ie_SubClass, ie->ie_Code, ie->ie_Qualifier, ie->ie_EventAddress, ie->ie_TimeStamp.tv_secs, ie->ie_TimeStamp.tv_micro));
  630. // DQ(bug(" %s\n", class_name(ie->ie_Class)));
  631.  
  632.  
  633. //    // --- Check for Doubleclick; putting it here would decrease
  634. //    //     speed, since the flag is checked on every IEvent ...
  635. //    //     pity, but can't help
  636. //    if (IS_CHECK_DBLCLICK) {
  637. //        MAKE_UNCHECKDBLCLICK();
  638. //        if (o == GDATA->last_selected) {
  639. //        if (DoubleClick(GDATA->last_selection.tv_secs, GDATA->last_selection.tv_micro, msg->gpi_InputEvent->ie_TimeStamp.tv_secs, msg->gpi_InputEvent->ie_TimeStamp.tv_micro )) {
  640. //            TRY_TO_DBLCLICK();
  641. //            return GMR_NOREUSE;
  642. //        } /* if */
  643. //        } /* if */
  644. //        GDATA->last_selected  = o;
  645. //        GDATA->last_selection = ie->ie_TimeStamp;
  646. //    } /* if */
  647.  
  648.  
  649.     if (ie->ie_Class != IECLASS_RAWMOUSE) {
  650.         return GMR_MEACTIVE;
  651.     } /* if */
  652.  
  653.     switch (ie->ie_Code) {
  654.     case SELECTUP: // --- drop! ... where ?
  655.         if (IS_VISIBLE) {
  656.         TRY_TO_DROP();
  657.         } /* if */
  658.         return GMR_NOREUSE;
  659.  
  660.     case MENUDOWN:        // --- abort or deselect all or only this one
  661.         if (!(ie->ie_Qualifier & IEQUALIFIER_ANYSHIFT))
  662.         DESELECT_ALL_BOBS();
  663.         else
  664.         if (!IS_VISIBLE) {
  665.             DESELECT();
  666.             RENDER();
  667.         } /* if */
  668.         return GMR_NOREUSE;
  669.  
  670.     default:
  671.         // --- securitycheck: haben wir ein selectup verpasst? ...
  672.         //       solange die Maus gedrueckt ist, weitermachen ...
  673.         if (!(ie->ie_Qualifier & IEQUALIFIER_LEFTBUTTON)) {
  674.         return GMR_NOREUSE;
  675.         } /* if */
  676.  
  677.         // --- lass ihn hidden solange es geht, dann zecihnen,
  678.         //       ansonsten Position nachhalten ...
  679.         // --- ich wuerde gerne eine Minimale Bewegung einbauen,
  680.         //       einen Schwellenwert, unter dem keine Bobs dargestellt
  681.         //       werden.
  682.         if ((ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE)) {
  683. #ifdef Threshold
  684.         if (!IS_VISIBLE) {
  685.             // --- Primitiver Threshold ...
  686.             //       die Routine Versagt, wenn
  687.             //       die Eingabe irgendwo zwischen 0 und THRESHOLD_?
  688.             //       endet ... (zB Selection,1 Pixel Movement,Release)
  689.             //       der naechste Bob wird falsch dargestellt 8-(
  690.             //       um das zu umgehen muessten wir die Weite in
  691.             //       GM_GO[IN]ACTIVE resetten, das geht aber nur mit
  692.             //       globalen daten ... (na gut, auch nicht schlechter
  693.             //       als statics)
  694.             //       da hat mir die alte version ja fast noch besser gefallen
  695.             // static int dist_X, dist_Y;
  696.             // static int rel_X, rel_Y;
  697.             dist_X += ABS(ie->ie_X);
  698.             dist_Y += ABS(ie->ie_Y);
  699.             GDATA->move_X += ie->ie_X;
  700.             GDATA->move_Y += ie->ie_Y;
  701.             if ((dist_X > THRESHOLD_X) || (dist_Y > THRESHOLD_Y)) {
  702.             SHOW_ALL_BOBS();
  703.             REL_MOVE_ALL_BOBS(GDATA->move_X, GDATA->move_Y);
  704.             dist_X = dist_Y = 0;
  705.             } /* if */
  706.         } else {
  707.             if ((ie->ie_X || ie->ie_Y)) {
  708.             REL_MOVE_ALL_BOBS(ie->ie_X, ie->ie_Y);
  709.             GDATA->move_X += ie->ie_X;
  710.             GDATA->move_Y += ie->ie_Y;
  711.             } /* if */
  712.         } /* if */
  713. #else
  714.         if ((ie->ie_X || ie->ie_Y)) {
  715.             if (!IS_VISIBLE)
  716.             SHOW_ALL_BOBS();
  717.             REL_MOVE_ALL_BOBS(ie->ie_X, ie->ie_Y);
  718.             GDATA->move_X += ie->ie_X;
  719.             GDATA->move_Y += ie->ie_Y;
  720.         } /* if */
  721. #endif
  722.         } else {
  723.         // --- hierfuer muesste ich die mauspos zwischenspeichern,
  724.         //     und die rel-werte jetzt bestimmen .... BWRRRRRRR
  725.         //     (bei jedem relmove aufaddieren)
  726.  DQ(bug("WARNING: **ABSMOUSE SKIPPED** \n", *(char*)0L));
  727. // reicht in ENFORCERHIT als Warnung ????????? 8^)
  728.         } /* if */
  729.  
  730.         return GMR_MEACTIVE;
  731.     } /* switch */
  732.  
  733.     return retval;
  734.  
  735.  
  736.  
  737.  
  738. ////////////////////////////////////////////////////////////
  739. //
  740. //  Minimal Test-Environment
  741. //
  742. ////////////////////////////////////////////////////////////
  743.  
  744. TEST_SUPPORT
  745.  
  746. #   define GEL_SIZE  4            /* number of lines in the bob     */
  747.  
  748.     /* data is 2 planes by 2 words by GEL_SIZE lines             */
  749.     WORD __chip bob_data[2 * 2 * GEL_SIZE] = {
  750.     /* plane 1 */
  751.     0xc000, 0xffff, 0xc000, 0x0fff, 0xc000, 0x0fff, 0xc000, 0xffff,
  752.     /* plane 2 */
  753.     0x3fff, 0xfffc, 0x3ff0, 0x0ffc, 0x3ff0, 0x0ffc, 0x3fff, 0xfffc
  754.     };
  755.     NEWBOB myNewBob = {
  756.     bob_data, 2,  GEL_SIZE,
  757.     2, 3, 0, SAVEBACK | OVERLAY,
  758.     0, 8, 160, 100,  0,0,
  759.     };
  760.  
  761. struct GlobalData *gimme_gdata (int cls) {
  762.     static struct GlobalData gdata;
  763.     if (cls) {
  764.     memset    (&gdata, sizeof (gdata), 0);
  765.     NewList ((struct List *)&gdata.list);
  766.     } /* if */
  767.     return &gdata;
  768. } /* gimme_gdata */
  769.  
  770.  
  771.  
  772. TEST_WINDOW
  773.     WA_IDCMP, IDCMP_CLOSEWINDOW,
  774.     WA_Title, "DragClass TestWindow",
  775.     WA_Width, 300,
  776.     WA_Height, 100,
  777.  
  778. TEST_OBJECT test_ob
  779.     GA_Top,    50,
  780.     GA_Left,    50,
  781.     GDA_NewBob, &myNewBob,
  782.     GDA_GData,    gimme_gdata(1),
  783.     GDA_FreePlacement, 1,
  784.  
  785. TEST_OBJECT test_ob2
  786.     GA_Previous,test_ob,
  787.     GA_Top,    50,
  788.     GA_Left,   120,
  789.     GDA_NewBob, &myNewBob,
  790.     GDA_GData,    gimme_gdata(0),
  791.     GDA_FreePlacement, 1,
  792.  
  793. TEST_OBJECT test_ob3
  794.     GA_Previous,test_ob2,
  795.     GA_Top,    50,
  796.     GA_Left,   190,
  797.     GDA_NewBob, &myNewBob,
  798.     GDA_GData,    gimme_gdata(0),
  799.  
  800.  
  801.  
  802.