home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0040 - 0049 / ibm0040-0049 / ibm0040.tar / ibm0040 / ZINC_6.ZIP / DOSSRC.ZIP / SCROLL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-01  |  12.1 KB  |  366 lines

  1. //    Zinc Interface Library - SCROLL.CPP
  2. //    COPYRIGHT (C) 1990, 1991.  All Rights Reserved.
  3. //    Zinc Software Incorporated.  Pleasant Grove, Utah  USA
  4.  
  5. #include "ui_win.hpp"
  6.  
  7. // Special button identifications - order is important.
  8. const int TOTAL_BUTTONS        = 5;
  9. const int TOP_BUTTON        = 0;
  10. const int LEFT_BUTTON        = 0;
  11. const int BOTTOM_BUTTON        = 1;
  12. const int RIGHT_BUTTON        = 1;
  13. const int MIDDLE_BUTTON        = 2;
  14. const int TOP_REGION        = 3;
  15. const int LEFT_REGION        = 3;
  16. const int BOTTOM_REGION        = 4;
  17. const int RIGHT_REGION        = 4;
  18.  
  19. void UIW_SCROLL_BAR::UserFunction(void *data, UI_EVENT &event)
  20. {
  21.     UIW_BUTTON *button = (UIW_BUTTON *)data;
  22.     UIW_SCROLL_BAR *scroll = (UIW_SCROLL_BAR *)button->parent;
  23.     int current = scroll->current;
  24.     if (button->value == TOP_BUTTON)
  25.         current--;
  26.     else if (button->value == BOTTOM_BUTTON)
  27.         current++;
  28.     else if (button->value == MIDDLE_BUTTON)
  29.     {
  30.         int size = scroll->display->isText ? 1 : scroll->display->cellWidth * 2;
  31.         long numerator = (long)(button->relative.top - scroll->button[TOP_BUTTON]->true.bottom) * (long)scroll->maximum;
  32.         long denominator = (long)(scroll->button[BOTTOM_BUTTON]->true.top - scroll->button[TOP_BUTTON]->true.bottom - size);
  33.         if (denominator > 0)
  34.             current = (int)(numerator / denominator);
  35.     }
  36.     else
  37.     {
  38.         event.type = (button->value == TOP_REGION) ? L_PGUP : L_PGDN;
  39.         if (scroll->Next())
  40.             scroll->Next()->Event(event);
  41.         return;
  42.     }
  43.  
  44.     if (current < 0)
  45.         current = 0;
  46.     else if (current > scroll->maximum)
  47.         current = scroll->maximum;
  48.  
  49.     for (UI_WINDOW_OBJECT *object = scroll->Next(); object; object = object->Next())
  50.         if (!FlagSet(object->woAdvancedFlags, WOAF_NON_CURRENT))
  51.             break;
  52.     if (object && current != scroll->current)
  53.     {
  54.         event.type = S_SCROLL_VERTICAL;
  55.         event.scroll.delta = scroll->current - current;
  56.           object->eventManager->Put(event, Q_BEGIN);
  57.         if (!FlagSet(object->woStatus, WOS_CURRENT))
  58.         {
  59.             event.type = L_BEGIN_SELECT;
  60.             event.position.column = object->true.left;
  61.             event.position.line = object->true.top;
  62.               object->eventManager->Put(event, Q_BEGIN);
  63.         }
  64.     }
  65. }
  66.  
  67. UIW_SCROLL_BAR::UIW_SCROLL_BAR(int left, int top, int width, int height,
  68.     USHORT _sbFlags, USHORT _woFlags) :
  69.     UIW_WINDOW(left, top, width, height, _woFlags, WOAF_NON_CURRENT),
  70.     sbFlags(_sbFlags), current(0), showing(0), maximum(0)
  71. {
  72.     // Initialize the slide information.
  73.     windowID[0] = ID_SCROLL_BAR;
  74.     windowID[1] = ID_WINDOW;
  75.     search.type = ID_SCROLL_BAR;
  76.  
  77.     // Check for the corner scroll-bar
  78.     if (!FlagSet(sbFlags, SBF_VERTICAL | SBF_HORIZONTAL))
  79.     {
  80.         button[0] = new UIW_BUTTON(0, 0, 0, "", BTF_NO_TOGGLE | BTF_NO_3D,
  81.             WOF_NON_FIELD_REGION | WOF_NON_SELECTABLE);
  82.         woFlags |= WOF_NON_SELECTABLE;
  83.         UI_LIST::Add(button[0]);
  84.         return;
  85.     }
  86.  
  87.     char *vertical[5] = { "\036", "\037", "\007", NULL, NULL };
  88.     char *horizontal[5] = { "\021", "\020", "\007", NULL, NULL };
  89.     for (int i = 0; i < TOTAL_BUTTONS; i++)
  90.     {
  91.         USHORT flags = (i >= TOP_REGION) ?
  92.             BTF_NO_TOGGLE | BTF_NO_3D : BTF_NO_TOGGLE;
  93.         button[i] = FlagSet(_sbFlags, SBF_VERTICAL) ?
  94.             new UIW_BUTTON(0, 0, 0, vertical[i], flags,
  95.             WOF_JUSTIFY_CENTER | WOF_NON_FIELD_REGION,
  96.             UIW_SCROLL_BAR::UserFunction, i) :
  97.             new UIW_BUTTON(0, 0, 0, horizontal[i], BTF_NO_TOGGLE | flags,
  98.             WOF_JUSTIFY_CENTER | WOF_NON_FIELD_REGION,
  99.             UIW_SCROLL_BAR::UserFunction, i);
  100.         if (i >= TOP_REGION)
  101.             button[i]->WindowID(0, ID_SCROLL_BAR);
  102.         button[i]->woAdvancedFlags |= WOAF_NON_CURRENT;
  103.         UI_LIST::Add(button[i]);
  104.     }
  105. }
  106.  
  107. UIW_SCROLL_BAR::Event(const UI_EVENT &event)
  108. {
  109.     static int deltaLine;
  110.  
  111.     // Switch on the event type.
  112.     int ccode = UI_WINDOW_OBJECT::LogicalEvent(event, ID_SCROLL_BAR);
  113.     switch (ccode)
  114.     {
  115.     case S_CREATE:
  116.     case S_SIZE:
  117.         // Compute the scroll bar position.
  118.         display->RegionConvert(relative, &woStatus, WOS_GRAPHICS);
  119.         if (!FlagSet(woFlags, WOF_NON_FIELD_REGION) && FlagSet(sbFlags, SBF_VERTICAL))
  120.             relative.right = display->isText ?
  121.                 relative.left : relative.left + 2 * display->cellWidth - 1;
  122.         else if (!FlagSet(woFlags, WOF_NON_FIELD_REGION) && FlagSet(sbFlags, SBF_HORIZONTAL))
  123.             relative.bottom = display->isText ?
  124.                 relative.top : relative.top + 2 * display->cellWidth - 1;
  125.         UI_WINDOW_OBJECT::RegionMax(FlagSet(sbFlags, SBF_VERTICAL) ? TRUE : FALSE);
  126.         int startButton = TOP_BUTTON;
  127.         int endButton = (ccode == S_CREATE) ? BOTTOM_BUTTON : BOTTOM_REGION;
  128.         if (FlagSet(sbFlags, SBF_VERTICAL))
  129.             VerticalCompute(startButton, endButton);
  130.         else if (FlagSet(sbFlags, SBF_HORIZONTAL))
  131.             HorizontalCompute(startButton, endButton);
  132.         else
  133.             CornerCompute();
  134.         break;
  135.  
  136.     case S_SCROLL_VERTICAL:
  137.     case S_SCROLL_HORIZONTAL:
  138.     case S_SCROLL_VERTICAL_SET:
  139.     case S_SCROLL_HORIZONTAL_SET:
  140.         if ((ccode == S_SCROLL_VERTICAL_SET && FlagSet(sbFlags, SBF_VERTICAL)) ||
  141.             (ccode == S_SCROLL_HORIZONTAL_SET && FlagSet(sbFlags, SBF_HORIZONTAL)))
  142.         {
  143.             showing = event.scroll.showing;
  144.             maximum = event.scroll.maximum;
  145.             current = event.scroll.current;
  146.             if (current > maximum)
  147.                 current = maximum;
  148.         }
  149.         else if ((ccode == S_SCROLL_VERTICAL && FlagSet(sbFlags, SBF_VERTICAL)) ||
  150.             (ccode == S_SCROLL_HORIZONTAL && FlagSet(sbFlags, SBF_HORIZONTAL)))
  151.         {
  152.             current -= event.scroll.delta;
  153.             if (current < 0)
  154.                 current = 0;
  155.             else if (current > maximum)
  156.                 current = maximum;
  157.         }
  158.         else if (previous)
  159.         {
  160.             Previous()->Event(event);
  161.             break;
  162.         }
  163.         if (FlagSet(sbFlags, SBF_VERTICAL))
  164.             VerticalCompute(MIDDLE_BUTTON, BOTTOM_REGION);
  165.         else if (FlagSet(sbFlags, SBF_HORIZONTAL))
  166.             HorizontalCompute(MIDDLE_BUTTON, RIGHT_REGION);
  167.         break;
  168.  
  169.     case L_BEGIN_SELECT:
  170.     case L_CONTINUE_SELECT:
  171.     case L_END_SELECT:
  172.         if (FlagSet(sbFlags, SBF_CORNER) || FlagSet(woAdvancedStatus, WOAS_TOO_SMALL))
  173.             break;
  174.         UIW_BUTTON *middle = button[MIDDLE_BUTTON];
  175.         if (ccode == L_BEGIN_SELECT && middle->Overlap(event.position) &&
  176.             !FlagSet(middle->woStatus, WOS_CURRENT) &&
  177.             !FlagSet(middle->woAdvancedStatus, WOAS_INVALID_REGION)) 
  178.         {
  179.             middle->woStatus |= WOS_CURRENT;
  180.             middle->relative = middle->true;
  181.             if (!display->isText)
  182.                 display->Rectangle(screenID, middle->relative, _xorPalette, 1, FALSE, TRUE);
  183.             deltaLine = event.position.line - middle->true.top;
  184.         }
  185.         else if (ccode == L_CONTINUE_SELECT &&
  186.             FlagSet(middle->woStatus, WOS_CURRENT))
  187.         {
  188.             int deltaY = 0;
  189.             if (FlagSet(sbFlags, SBF_VERTICAL))
  190.             {
  191.                 deltaY = event.position.line - middle->true.top - deltaLine;
  192.                 if (middle->true.top + deltaY < button[TOP_BUTTON]->true.bottom)
  193.                     deltaY = button[TOP_BUTTON]->true.bottom - middle->true.top;
  194.                 else if (middle->true.bottom + deltaY > button[BOTTOM_BUTTON]->true.top)
  195.                     deltaY = button[BOTTOM_BUTTON]->true.top - middle->true.bottom;
  196.             }
  197.             UI_REGION region = middle->true;
  198.             region.top += deltaY;
  199.             region.bottom += deltaY;
  200.             if (!display->isText)
  201.                 display->RectangleXORDiff(middle->relative, region);
  202.             middle->relative = region;
  203.         }
  204.         else if (ccode == L_END_SELECT && FlagSet(middle->woStatus, WOS_CURRENT))
  205.         {
  206.             if (!display->isText)
  207.                 display->Rectangle(screenID, middle->relative, _xorPalette, 1, FALSE, TRUE);
  208.             UI_EVENT tEvent = event;
  209.             UIW_SCROLL_BAR::UserFunction(middle, tEvent);
  210.             middle->woStatus &= ~WOS_CURRENT;
  211.         }
  212.         else
  213.             UIW_WINDOW::Event(event);
  214.         break;
  215.  
  216.     default:
  217.         ccode = UIW_WINDOW::Event(event);
  218.         break;
  219.     }
  220.  
  221.     // Return the event control code.
  222.     return (ccode);
  223. }
  224.  
  225. void *UIW_SCROLL_BAR::Information(INFORMATION_REQUEST request, void *data)
  226. {
  227.     if (request == GET_NUMBERID_OBJECT || request == GET_STRINGID_OBJECT ||
  228.         request == PRINT_INFORMATION)
  229.         return (UIW_WINDOW::Information(request, data));
  230.     else
  231.         return (UI_WINDOW_OBJECT::Information(request, data));
  232. }
  233.  
  234. void UIW_SCROLL_BAR::CornerCompute()
  235. {
  236.     int size = display->cellWidth * 2;
  237.     if (true.left < true.right - size + 1)
  238.         true.left = true.right - size + 1;
  239.     if (true.top < true.bottom - size + 1)
  240.         true.top = true.bottom - size + 1;
  241.  
  242.     UIW_BUTTON *tButton = button[0];
  243.     tButton->InformationSet(screenID, display, eventManager,
  244.         windowManager, paletteMapTable, this);
  245.     UI_EVENT event;
  246.     event.type = S_CREATE;
  247.     tButton->Event(event);
  248. }
  249.  
  250. void UIW_SCROLL_BAR::HorizontalCompute(int startButton, int endButton)
  251. {
  252.     int size = display->isText ? display->cellWidth : display->cellWidth * 2;
  253.     if (FlagSet(woFlags, WOF_NON_FIELD_REGION) && true.top < true.bottom - size + 1)
  254.         true.top = true.bottom - size + 1;
  255.     if (size > (true.right - true.left) / 2)
  256.         size = (true.right - true.left) / 2;
  257.     for (int i = startButton; i <= endButton; i++)
  258.     {
  259.         UIW_BUTTON *tButton = button[i];
  260.         tButton->InformationSet(screenID, display, eventManager,
  261.             windowManager, paletteMapTable, this);
  262.         UI_EVENT event;
  263.         event.type = S_CREATE;
  264.         tButton->Event(event);
  265.         if (i == LEFT_BUTTON)
  266.             tButton->true.right = tButton->true.left + size - 1;
  267.         else if (i == RIGHT_BUTTON)
  268.             tButton->true.left = tButton->true.right - size + 1;
  269.         else if (i == MIDDLE_BUTTON && tButton->true.right - tButton->true.left > size)
  270.         {
  271.             if (maximum <= 0)
  272.                 maximum = showing = current = 1;
  273.             int width = tButton->true.right - tButton->true.left;
  274.             int tSize = FlagSet(sbFlags, SBF_SIZE_MIDDLE) ?
  275.                 size + (int)((long)(width - size) * showing / maximum) :
  276.                 size;
  277.             tButton->true.left += (int)((long)(width - tSize) * current / maximum);
  278.             tButton->true.right = tButton->true.left + tSize;
  279.         }
  280.         if (tButton->true.left >= tButton->true.right ||
  281.             (i == LEFT_REGION && tButton->true.left > button[MIDDLE_BUTTON]->true.right))
  282.             tButton->woAdvancedStatus |= WOAS_INVALID_REGION;
  283.         else if (endButton != RIGHT_BUTTON && !FlagSet(woAdvancedStatus, WOAS_INVALID_REGION))
  284.         {
  285.             event.type = S_DISPLAY_ACTIVE;
  286.             event.region = tButton->true;
  287.             tButton->Event(event);
  288.         }
  289.     }
  290. }
  291.  
  292. void UIW_SCROLL_BAR::VerticalCompute(int startButton, int endButton)
  293. {
  294.     int size = display->isText ? display->cellWidth : display->cellWidth * 2;
  295.     if (FlagSet(woFlags, WOF_NON_FIELD_REGION) && true.left < true.right - size + 1)
  296.         true.left = true.right - size + 1;
  297.     if (size > (true.bottom - true.top) / 2)
  298.         size = (true.bottom - true.top) / 2;
  299.     for (int i = startButton; i <= endButton; i++)
  300.     {
  301.         UIW_BUTTON *tButton = button[i];
  302.         tButton->InformationSet(screenID, display, eventManager,
  303.             windowManager, paletteMapTable, this);
  304.         UI_EVENT event;
  305.         event.type = S_CREATE;
  306.         tButton->Event(event);
  307.         if (i == TOP_BUTTON)
  308.             tButton->true.bottom = tButton->true.top + size - 1;
  309.         else if (i == BOTTOM_BUTTON)
  310.             tButton->true.top = tButton->true.bottom - size + 1;
  311.         else if (i == MIDDLE_BUTTON && tButton->true.bottom - tButton->true.top > size)
  312.         {
  313.             if (maximum <= 0)
  314.                 maximum = showing = current = 1;
  315.             int height = tButton->true.bottom - tButton->true.top;
  316.             int tSize = FlagSet(sbFlags, SBF_SIZE_MIDDLE)  ?
  317.                 size + (int)((long)(height - size) * showing / maximum) :
  318.                 size;
  319.             tButton->true.top += (int)((long)(height - tSize) * current / maximum);
  320.             tButton->true.bottom = tButton->true.top + tSize;
  321.         }
  322.         if (tButton->true.top > tButton->true.bottom ||
  323.             (i == TOP_REGION && tButton->true.top > button[MIDDLE_BUTTON]->true.bottom))
  324.             tButton->woAdvancedStatus |= WOAS_INVALID_REGION;
  325.         else if (endButton != BOTTOM_BUTTON && !FlagSet(woAdvancedStatus, WOAS_INVALID_REGION))
  326.         {
  327.             event.type = S_DISPLAY_ACTIVE;
  328.             event.region = tButton->true;
  329.             tButton->Event(event);
  330.         }
  331.     }
  332. }
  333.  
  334. #ifdef ZIL_LOAD
  335. UIW_SCROLL_BAR::UIW_SCROLL_BAR(const char *name, UI_STORAGE *file, USHORT loadFlags) :
  336.     UIW_WINDOW(name, file, loadFlags | L_SUB_LEVEL),
  337.     current(0), showing(0), maximum(0)
  338. {
  339.     windowID[0] = ID_SCROLL_BAR;
  340.     windowID[1] = ID_WINDOW;
  341.  
  342.     if (!file)
  343.         file = _storage;
  344.     file->Load(&sbFlags);
  345.     int i = 0;
  346.     for (UI_WINDOW_OBJECT *object = First(); object; object = object->Next())
  347.     {
  348.         if (i >= TOP_REGION)
  349.             object->WindowID(0, ID_SCROLL_BAR);
  350.         button[i++] = (UIW_BUTTON *)object;
  351.     }
  352.     if (!FlagSet(loadFlags, L_SUB_LEVEL) && FlagSet(file->stStatus, STS_TEMPORARY))
  353.         delete file;
  354. }
  355. #endif
  356.  
  357. #ifdef ZIL_STORE
  358. void UIW_SCROLL_BAR::Store(const char *name, UI_STORAGE *file, USHORT storeFlags)
  359. {
  360.     UIW_WINDOW::Store(name, file, storeFlags | S_SUB_LEVEL);
  361.     file->Store(sbFlags);
  362.     if (!FlagSet(storeFlags, S_SUB_LEVEL))
  363.         file->ObjectSize(name, search);
  364. }
  365. #endif
  366.