home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / v / vista / c / wins < prev   
Text File  |  1996-02-01  |  26KB  |  1,052 lines

  1. // **************************************************************************
  2. //                     Copyright 1996 David Allison
  3. //
  4. //             VV    VV    IIIIII     SSSSS     TTTTTT       AA
  5. //             VV    VV      II      SS           TT       AA  AA
  6. //             VV    VV      II        SSSS       TT      AA    AA
  7. //              VV  VV       II           SS      TT      AAAAAAAA
  8. //                VV       IIIIII     SSSS        TT      AA    AA
  9. //
  10. //                    MULTI-THREADED C++ WIMP CLASS LIBRARY
  11. //                                for RISC OS
  12. // **************************************************************************
  13. //
  14. //             P U B L I C    D O M A I N    L I C E N C E
  15. //             -------------------------------------------
  16. //
  17. //     This library is copyright. You may not sell the library for
  18. //     profit, but you may sell products which use it providing
  19. //     those products are presented as executable code and are not
  20. //     libraries themselves.  The library is supplied without any
  21. //     warranty and the copyright owner cannot be held responsible for
  22. //     damage resulting from failure of any part of this library.
  23. //
  24. //          See the User Manual for details of the licence.
  25. //
  26. // *************************************************************************
  27.  
  28. #include "Vista:task.h"
  29. #include "Vista:wins.h"
  30. #include <kernel.h>
  31. #include <swis.h>
  32. #include "icon.h"
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <stdarg.h>
  37.  
  38. #ifndef __EASY_C
  39. #include "Vista:myargs.h"
  40. #endif
  41.  
  42. //
  43. // An IconGrid
  44. //
  45.  
  46. // this has a window with a vertical scroll bar and can be resized.
  47. // It traps the open event from the Wimp and checks the current size
  48. // of the window.  If it can rearrange the icons it will.
  49. //
  50.  
  51. IconGrid::IconGrid (Task *task, char *tname, int ticon, char *menu)
  52.  : Window (task, tname, menu)
  53.    {
  54.    init (ticon) ;
  55.    }
  56.  
  57. IconGrid::IconGrid (Window *w, char *tname, int ticon, char *menu)
  58.  : Window (w, tname, 0, menu)
  59.    {
  60.    init (ticon) ;
  61.    }
  62.  
  63.  
  64. IconGrid::~IconGrid()
  65.    {
  66.    }
  67.  
  68. void IconGrid::init (int ticon)
  69.    {
  70.    _kernel_swi_regs r ;
  71.    _kernel_oserror *e ;
  72.    int block[40] ;
  73.  
  74.    template_icon = new Icon (this, ticon) ;
  75.    template_icon->move_to (-1000,1000) ;     // move the icon out of sight
  76.    block[0] = handle ;
  77.    block[1] = ticon ;
  78.    r.r[1] = (int)block ;
  79.    if ((e = _kernel_swi (Wimp_GetIconState, &r, &r)) != NULL)
  80.       throw (e) ;
  81.    template_button_type = (Icon::buttontype)((block[6] & 0xf000) >> 12) ;
  82.    Box *box = (Box*)&block[2] ;
  83.    icon_height = box->y1 - box->y0 ;
  84.    icon_width = box->x1 - box->x0 ;
  85.    num_rows = 0 ;
  86.    num_icons = 0 ;
  87.    current_column = 0 ;
  88.    current_row = 0 ;
  89.    num_columns = (x1 - x0 - ICONGRID_LEFT_MARGIN) / (icon_width + ICONGRID_HOR_GAP) ;
  90.    if (num_columns == 0)
  91.       num_columns = 1 ;
  92.    flag_set = NONE ;
  93.    Window::Info *inf = info() ;
  94.    min_height = inf->extent.y1 - inf->extent.y0 ;
  95.    }
  96.  
  97.  
  98. void IconGrid::set_flag (flags flag)
  99.    {
  100. #ifndef __EASY_C
  101.    int f = (int)flag_set ;
  102.    f |= (int)flag ;
  103.    flag_set = (flags)f ;
  104. #else
  105.    flag_set |= (flags)flag ;
  106. #endif
  107.    }
  108.  
  109. void IconGrid::clear_flag (flags flag)
  110.    {
  111. #ifndef __EASY_C
  112.    int f = (int)flag_set ;
  113.    f &= ~(int)flag ;
  114.    flag_set = (flags)f ;
  115. #else
  116.    flag_set |= (flags)flag ;
  117. #endif
  118.    }
  119.  
  120. //
  121. // add a new icon into the window.  This will fill up the window from
  122. // left to right taking a new row when a row is full.
  123. //
  124.  
  125. Icon *IconGrid::insert_icon(char *text, void *ref)
  126.    {
  127.    int x, y ;
  128.  
  129.    x = current_column * (icon_width + ICONGRID_HOR_GAP) + ICONGRID_LEFT_MARGIN ;
  130.    y = current_row * (icon_height + ICONGRID_VERT_GAP) + icon_height +ICONGRID_TOP_MARGIN ;
  131.  
  132.    Icon *icon = new Icon (this, template_icon, x, -y, ref) ;
  133.    Box pos ;
  134.    icon->read_position (pos) ;
  135.    do_redraw (pos.x0, pos.y0, pos.x1, pos.y1) ;    // redraw the window
  136.    icon->print (text) ;
  137.    num_icons++ ;
  138.    current_column++ ;
  139.    if (current_column == num_columns)
  140.       {
  141.       current_column = 0 ;
  142.       current_row++ ;
  143.       int new_height = current_row * (icon_height + ICONGRID_VERT_GAP) + icon_height +ICONGRID_TOP_MARGIN ;
  144.       if (new_height > min_height)
  145.          set_height (new_height) ;
  146.       }
  147.    if (flag_set & SORTED)
  148.       sort() ;
  149.    return icon ;
  150.    }
  151.  
  152. Icon *IconGrid::insert_icon(char *text, char *sprite, void *ref)
  153.    {
  154.    int x, y ;
  155.  
  156.    x = current_column * (icon_width + ICONGRID_HOR_GAP) + ICONGRID_LEFT_MARGIN ;
  157.    y = current_row * (icon_height + ICONGRID_VERT_GAP) + icon_height +ICONGRID_TOP_MARGIN ;
  158.  
  159.    Icon *icon = new Icon (this, template_icon, x, -y, ref) ;
  160.    Box pos ;
  161.    icon->read_position (pos) ;
  162.    do_redraw (pos.x0, pos.y0, pos.x1, pos.y1) ;    // redraw the window
  163.    icon->print (text) ;
  164.    icon->change_sprite (sprite) ;
  165.    num_icons++ ;
  166.    current_column++ ;
  167.    if (current_column == num_columns)
  168.       {
  169.       current_column = 0 ;
  170.       current_row++ ;
  171.       int new_height = current_row * (icon_height + ICONGRID_VERT_GAP) + icon_height +ICONGRID_TOP_MARGIN ;
  172.       if (new_height > min_height)
  173.          set_height (new_height) ;
  174.       }
  175.    if (flag_set & SORTED)
  176.       sort() ;
  177.    return icon ;
  178.    }
  179.  
  180.  
  181. void IconGrid::remove_icon(Icon *icon)
  182.    {
  183.    Window::remove_icon (icon) ;
  184.    if (!deleting)
  185.       {
  186.       num_icons-- ;
  187.       if (flag_set & SORTED)
  188.          sort() ;
  189.       }
  190.    }
  191.  
  192. void IconGrid::delete_icon (void *ref)
  193.    {
  194.    for (Icon *icon = icons ; icon != NULL ; icon = icon->next)
  195.       if (ref == icon->user_ref)
  196.          {
  197.          delete icon ;
  198.          break ;
  199.          }
  200.    }
  201.  
  202. //
  203. // sort the icons in the grid using qsort
  204. //
  205.  
  206.  
  207. static int sort_compare (const void *i1, const void *i2)
  208.    {
  209.    const Icon **x = (const Icon**)i1 ;
  210.    const Icon **y = (const Icon**)i2 ;
  211. #ifdef __EASY_C
  212.    return (*x)->compare(*y) ;
  213. #else
  214.    Icon *i = (Icon*)*x ;
  215.    Icon *j = (Icon*)*y ;
  216.    return i->compare(j) ;
  217. #endif
  218.    }
  219.  
  220.  
  221. void IconGrid::sort()
  222.    {
  223.    int i ;
  224.    Icon *icon ;
  225.    Icon **buffer = new Icon *[num_icons] ;
  226.    for (icon = icons, i = 0 ; icon != NULL ; icon = icon->next)
  227.       if (icon != template_icon)
  228.          buffer[i++] = icon ;
  229.    qsort (buffer, num_icons, sizeof (Icon *), sort_compare) ;
  230.    icons = NULL ;               // reset icons list
  231.    add_icon (template_icon) ;   // add the template again
  232.    for (i = 0 ; i < num_icons ; i++)     // put all the icons back
  233.       add_icon (buffer[i]) ;
  234.    rearrange() ;
  235.    delete [] buffer ;
  236.    }
  237.  
  238.  
  239. void IconGrid::open(int x0, int y0, int x1, int y1, int scx, int scy, int behind)
  240.   {
  241.   Window::open (x0,y0,x1,y1,scx,scy,behind) ;   // open the window
  242.   int nc = (x1 - x0 - ICONGRID_LEFT_MARGIN) / (icon_width + ICONGRID_HOR_GAP) ;
  243.   if (nc == 0)
  244.     nc = 1 ;
  245.   if (num_icons != 0 && nc != num_columns)
  246.      {
  247.      num_columns = nc ;
  248.      rearrange() ;
  249.      }
  250.   num_columns = nc ;
  251.   }
  252.  
  253.  
  254. void IconGrid::click(int mx, int my, int buttons, int icon)
  255.    {
  256.    int click_factor ;
  257.    int double_factor ;
  258.    int drag_factor ;
  259.    switch (template_button_type)
  260.       {
  261.       case Icon::BCLICKDEBOUNCE:
  262.          click_factor = 1 ;
  263.          double_factor = 0 ;
  264.          drag_factor = 0 ;
  265.          break ;
  266.       case Icon::BDEBOUNCEDRAG:
  267.       default:
  268.          click_factor = 1 ;
  269.          double_factor = 0 ;
  270.          drag_factor = 16 ;
  271.          break ;
  272.       case Icon::BCLICKDRAGDOUBLE:
  273.          click_factor = 256 ;
  274.          double_factor = 1 ;
  275.          drag_factor = 16 ;
  276.          break ;
  277.       }
  278.    if (icon >= 0)
  279.       {
  280.       Icon *ic = Window::find_icon (icon) ;
  281.       if (buttons & (4 * drag_factor))
  282.          {
  283.          int count = 0 ;
  284.          int minx = 30000, maxx = 0, miny = 0, maxy = -30000;
  285.          Box pos ;
  286.          for (Icon *i = icons ; i != NULL ; i = i->next)
  287.             if (i->is_selected())
  288.                {
  289.                count++ ;
  290.                i->read_position(pos) ;
  291.                if (pos.x0 < minx) minx = pos.x0 ;
  292.                if (pos.x1 > maxx) maxx = pos.x1 ;
  293.                if (pos.y0 < miny) miny = pos.y0 ;
  294.                if (pos.y1 > maxy) maxy = pos.y1 ;
  295.                }
  296.          minx += x0 ;
  297.          miny += y1 ;
  298.          maxx += x0 ;
  299.          maxy += y1 ;
  300.          if (count > 1)
  301.             drag_selection (mx, my, buttons, minx, miny, maxx, maxy) ;