home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / program / gempp15b / gemw.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-23  |  24.2 KB  |  1,166 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  This file is Copyright 1992,1993 by Warwick W. Allison.
  4. //  This file is part of the gem++ library.
  5. //  You are free to copy and modify these sources, provided you acknowledge
  6. //  the origin by retaining this notice, and adhere to the conditions
  7. //  described in the file COPYING.LIB.
  8. //
  9. //  (Extensions made in 1992 by Andre Pareis.)
  10. //
  11. /////////////////////////////////////////////////////////////////////////////
  12.  
  13. #include <aesbind.h>
  14. #include <bool.h>
  15. #include "gema.h"
  16. #include "gemw.h"
  17. #include "contract.h"
  18.  
  19.  
  20. ////////////////////////////////////////
  21. //    constructors, destructor
  22. ////////////////////////////////////////
  23.  
  24. GEMwindow::GEMwindow(GEMactivity& in, int Parts) :
  25.     parts(Parts),
  26.     xoff(0), yoff(0),
  27.     opened(FALSE), created(FALSE), initialized(FALSE),
  28.     xalign(1), yalign(1),
  29.     act(0)
  30. {
  31.     Pos = Max = GRect(0, 0, 0, 0);
  32.     *(info = new char[1]) = 0;    // create an empty string
  33.     *(name = new char[1]) = 0;        // create an empty name
  34.     visibleLines = 0;
  35.     totalLines = 0;
  36.     actualTopLine = 0;
  37.     visibleColumns = 0;
  38.     totalColumns = 0;
  39.     actualLeftColumn = 0;
  40.     lineHeight = 1;
  41.     columnWidth = 1;
  42.  
  43.     if (parts<0) {
  44.         handle = 0;
  45.         Create();
  46.     }
  47.  
  48.     InActivity(in);
  49. }
  50.  
  51.  
  52. GEMwindow::GEMwindow(GEMactivity& in, int Parts, const GRect& actWorkArea, const GRect& maxWorkArea) :
  53.     parts(Parts),
  54.     Pos(actWorkArea), Max(maxWorkArea), handle(0),
  55.     opened(FALSE), created(FALSE), initialized(TRUE),
  56.     xoff(0), yoff(0),
  57.     xalign(1), yalign(1),
  58.     act(0)
  59. {
  60.     *(info = new char[1]) = 0;    // create an empty string
  61.     *(name = new char[1]) = 0;        // create an empty name
  62.     visibleLines = 0;
  63.     totalLines = 0;
  64.     actualTopLine = 0;
  65.     visibleColumns = 0;
  66.     totalColumns = 0;
  67.     actualLeftColumn = 0;
  68.     lineHeight = 1;
  69.     columnWidth = 1;
  70.  
  71.     if (parts<0) {
  72.         handle = 0;
  73.         Create();
  74.     }
  75.  
  76.     InActivity(in);
  77. }
  78.  
  79.  
  80. GEMwindow::GEMwindow(GEMactivity& in, int Parts, const GRect& workArea) :
  81.     parts(Parts),
  82.     Pos(workArea), Max(workArea), handle(0),
  83.     opened(FALSE), created(FALSE), initialized(TRUE),
  84.     xoff(0), yoff(0),
  85.     xalign(1), yalign(1),
  86.     act(0)
  87. {
  88.     *(info = new char[1]) = 0;    // create an empty string
  89.     *(name = new char[1]) = 0;        // create an empty name
  90.     visibleLines = 0;
  91.     totalLines = 0;
  92.     actualTopLine = 0;
  93.     visibleColumns = 0;
  94.     totalColumns = 0;
  95.     actualLeftColumn = 0;
  96.     lineHeight = 1;
  97.     columnWidth = 1;
  98.  
  99.     if (parts<0) {
  100.         handle = 0;
  101.         Create();
  102.     }
  103.  
  104.     InActivity(in);
  105. }
  106.  
  107. GEMwindow::GEMwindow(const GEMwindow& copy) :
  108.     parts(copy.parts), Pos(copy.Pos), Max(copy.Max),
  109.     handle(0), opened(FALSE), created(FALSE),
  110.     initialized(copy.initialized),
  111.     xoff(copy.xoff), yoff(copy.yoff),
  112.     xalign(copy.xalign), yalign(copy.yalign),
  113.     info(strdup(copy.info)),
  114.     name(strdup(copy.name)),
  115.     visibleLines(copy.visibleLines),
  116.     totalLines(copy.totalLines),
  117.     actualTopLine(copy.actualTopLine),
  118.     visibleColumns(copy.visibleColumns),
  119.     totalColumns(copy.totalColumns),
  120.     actualLeftColumn(copy.actualLeftColumn),
  121.     act(0),
  122.     storer(copy.storer),
  123.     vSize(copy.vSize), vPosition(copy.vSize),
  124.     hSize(copy.vSize), hPosition(copy.vSize),
  125.     lineHeight(copy.lineHeight),
  126.     columnWidth(copy.columnWidth)
  127. {
  128.     GRect win=BorderRect();
  129.     win.g_x+=10;
  130.     win.g_y+=10;
  131.     Move(win.g_x,win.g_y);
  132.  
  133.     // If the original window was in an activity, put this one in there too.
  134.     if (copy.act) InActivity(*copy.act);
  135. }
  136.  
  137. GEMwindow::~GEMwindow()
  138. {
  139.     if (act) act->RemoveWindow(*this);
  140.  
  141.     if (IsOpen())
  142.         Close();
  143.  
  144.     if (IsCreated())
  145.         Delete();
  146.     
  147.     delete info;
  148.     delete name;
  149.  
  150.     Ensure(!IsCreated());
  151. }
  152.  
  153.  
  154. void GEMwindow::RedrawOverlaps(const GRect& area)
  155. // Standard algorithm found in all GEM code... that's why we have classes!
  156. {
  157.     GRect box,
  158.         dirty_dest,
  159.         work_area = WorkRect();
  160.  
  161.     wind_update(BEG_UPDATE);
  162.     graf_mouse(M_OFF, 0);
  163.  
  164.     wind_get(handle, WF_FIRSTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  165.  
  166.     while (box.g_w && box.g_h)
  167.     {
  168.         if (rc_intersect(&(GRect&)area, &box))
  169.         {
  170.             rc_copy(&box, &dirty_dest);
  171.             
  172.             if (rc_intersect(&work_area, &dirty_dest))
  173.                 Redraw(dirty_dest);
  174.         }
  175.         wind_get(handle, WF_NEXTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  176.     }
  177.     
  178.     graf_mouse(M_ON, 0);
  179.     wind_update(END_UPDATE);
  180. }
  181.  
  182.  
  183. ////////////////////////////////////////////////////////////////////////
  184. //
  185. // SPC:    Redraw(GRect& area)
  186. //    -- this method should be redefined in client classes
  187. //
  188. ////////////////////////////////////////////////////////////////////////
  189.  
  190. void GEMwindow::Redraw(const GRect& area)
  191. {
  192.     // clients should clip the 'area' and draw the window contents
  193. }
  194.  
  195. void GEMwindow::Open()
  196. {
  197.     if (!IsOpen()) {
  198.         Create();
  199.         if (!IsCreated()) return;
  200.  
  201.         VAlignSlider();
  202.         HAlignSlider();
  203.         VFlushSlider();
  204.         HFlushSlider();
  205.         wind_set(handle, WF_NAME, name, 0, 0);
  206.         wind_set(handle, WF_INFO, info, 0, 0);
  207.  
  208.         GRect    win = BorderRect();
  209.  
  210.         wind_open(handle, win.g_x, win.g_y, win.g_w, win.g_h);
  211.         opened = TRUE;
  212.     } else {
  213.         wind_set(handle, WF_TOP);
  214.     }
  215.  
  216.     if (act) act->Topped(*this);
  217.  
  218.     Ensure(IsOpen());
  219. }
  220.  
  221. void GEMwindow::Close()
  222. {
  223.     if (IsOpen() && handle) {
  224.         wind_close(handle);
  225.         opened = FALSE;
  226.         act->Bottomed(*this);
  227.         Delete();
  228.     }
  229. }
  230.  
  231.  
  232. ////////////////////////////////////////////////////////////////////////
  233. //
  234. // SPC:    move(int x, int y)
  235. //    -- Move() moves the window to the upper left point (x, y) and
  236. //    -- performs the move at screen if the window is opened
  237. //
  238. ////////////////////////////////////////////////////////////////////////
  239.  
  240. void GEMwindow::Move(int x, int y)
  241. {
  242.     GRect    win = BorderRect();
  243.     GRect    root;
  244.  
  245.     win.MoveAbs((x+xoff+xalign/2)/xalign*xalign-xoff,
  246.         (y+yoff+yalign/2)/yalign*yalign-yoff);
  247.     
  248.     wind_get(0, WF_WORKXYWH, &root.g_x, &root.g_y, &root.g_w, &root.g_h);
  249.  
  250.     if (win.g_x < root.g_x)
  251.         win.g_x = root.g_x;
  252.     if (win.g_y < root.g_y)
  253.         win.g_y = root.g_y;
  254.  
  255.     SetBorderRect(win);
  256. }
  257.  
  258. void GEMwindow::Top(const GEMevent&)
  259. {
  260.     if (handle && IsOpen()) {
  261.         wind_set(handle, WF_TOP);
  262.         act->Topped(*this);
  263.     }
  264. }
  265.  
  266. GEMfeedback GEMwindow::Click(const GEMevent&)
  267. {
  268.     return ContinueInteraction;
  269. }
  270.  
  271.  
  272. void GEMwindow::Align(int x, int y, int xmult=8, int ymult=1)
  273. {
  274.     xoff=x;
  275.     yoff=y;
  276.  
  277.     // Ignore 0 multiples!
  278.     if (xmult) xalign=xmult;
  279.     if (ymult) yalign=ymult;
  280. }
  281.  
  282. void GEMwindow::InActivity(GEMactivity& in)
  283. {
  284.     in.AddWindow(*this);
  285.     act=∈
  286. }
  287.  
  288.  
  289. ////////////////////////////////////////////////////////////////////////
  290. //
  291. //    Here are the extensions added by A.Pareis:
  292. //
  293. ////////////////////////////////////////////////////////////////////////
  294.  
  295.  
  296.  
  297. ////////////////////////////////////////////////////////////////////////
  298. //
  299. // SPC:    Create()
  300. //    -- Create() creates the real window how GEM knows it;
  301. //    -- the returned value signals the success of the operation
  302. //
  303. ////////////////////////////////////////////////////////////////////////
  304.  
  305. bool GEMwindow::Create()
  306. {
  307.     Require(!IsCreated());
  308.     if (IsCreated()) return FALSE;
  309.     
  310.     GRect win;
  311.     
  312.     if (!initialized) {
  313.         // i.e., no rectangles given
  314.         wind_get(0, WF_WORKXYWH, &win.g_x, &win.g_y, &win.g_w, &win.g_h);
  315.         Pos = Max = Win2Work(win);
  316.         initialized = TRUE;
  317.     } else
  318.         win = BorderRect();
  319.  
  320.     if (parts<0) {
  321.         handle=0; // ie. Desktop
  322.         parts=0;
  323.     } else {
  324.         handle = wind_create(parts, win.g_x, win.g_y, win.g_w, win.g_h);
  325.     }
  326.     
  327.     if (handle>=0)            // if succesfully created
  328.         created = TRUE;
  329.     
  330.     return created;
  331. }
  332.  
  333.  
  334.  
  335.  
  336. ////////////////////////////////////////////////////////////////////////
  337. //
  338. // SPC:    Delete()
  339. //    -- delete the real GEM window, but not the instance of this class
  340. //    -- if the window is opened, close it first
  341. //
  342. ////////////////////////////////////////////////////////////////////////
  343.  
  344. void GEMwindow::Delete()
  345. {
  346.     if (IsCreated()) {
  347.         if (IsOpen())
  348.             Close();
  349.  
  350.         if (handle) wind_delete(handle);
  351.         created = FALSE;
  352.     
  353.         Ensure(!IsCreated());
  354.     }
  355. }
  356.  
  357.  
  358.  
  359.  
  360.  
  361. ////////////////////////////////////////////////////////////////////////
  362. //
  363. // SPC:    BecomeDeleted()
  364. //
  365. ////////////////////////////////////////////////////////////////////////
  366.  
  367. void GEMwindow::BecomeDeleted()
  368. {
  369.     if (IsCreated()) {
  370.         opened = FALSE;
  371.         created = FALSE;
  372.     
  373.         Ensure(!IsCreated());
  374.     }
  375. }
  376.  
  377.  
  378.  
  379.  
  380.  
  381. ////////////////////////////////////////////////////////////////////////
  382. //
  383. // SPC:    SetBorderRect(GRect& newPos)
  384. //    -- the window may be moved and resized, if it is opened, the
  385. //    -- action will be performed at screen, too
  386. //
  387. ////////////////////////////////////////////////////////////////////////
  388.  
  389. void GEMwindow::SetBorderRect(const GRect& newPos)
  390. {
  391.     SetWorkRect(Win2Work(newPos));
  392. }
  393.  
  394.  
  395.  
  396. void GEMwindow::SetWorkRect(const GRect& newPos)
  397. {
  398.     Pos = newPos;
  399.  
  400.     if (parts&HSLIDE && Pos.g_w/columnWidth > totalColumns)
  401.         Pos.g_w=columnWidth * totalColumns;
  402.  
  403.     if (parts&HSLIDE && Pos.g_h/lineHeight > totalLines)
  404.         Pos.g_h=lineHeight * totalLines;
  405.  
  406.     // Round size down to nearest document unit
  407.     Pos.g_w-=Pos.g_w%columnWidth;
  408.     Pos.g_h-=Pos.g_h%lineHeight;
  409.  
  410.     GRect win = BorderRect();
  411.  
  412.     if (IsOpen() && handle)
  413.         wind_set(handle, WF_CURRXYWH, win.g_x, win.g_y, win.g_w, win.g_h);
  414.  
  415.     if (parts&HSLIDE && Pos.g_w/columnWidth != visibleColumns)
  416.         SetVisibleColumns(Pos.g_w/columnWidth);
  417.  
  418.     if (parts&VSLIDE && Pos.g_h/lineHeight != visibleLines)
  419.         SetVisibleLines(Pos.g_h/lineHeight);
  420. }
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427. ////////////////////////////////////////////////////////////////////////
  428. //
  429. // SPC:    Resize(int w, int h)
  430. //
  431. ////////////////////////////////////////////////////////////////////////
  432.  
  433. void GEMwindow::Resize(int w, int h)
  434. {
  435.     GRect    win = BorderRect();
  436.     
  437.     win.Resize(w, h);
  438.  
  439.     SetBorderRect(win);
  440. }
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447. GRect GEMwindow::Win2Work(const GRect& outer) const
  448. {
  449.     GRect    tmp;
  450.     
  451.     wind_calc(WC_WORK, parts < 0 ? 0 : parts, outer.g_x, outer.g_y, outer.g_w, outer.g_h,
  452.             &tmp.g_x, &tmp.g_y, &tmp.g_w, &tmp.g_h);
  453.     
  454.     return tmp;
  455. }
  456.  
  457.  
  458. GRect GEMwindow::Work2Win(const GRect& work) const
  459. {
  460.     GRect    tmp;
  461.     
  462.     wind_calc(WC_BORDER, parts < 0 ? 0 : parts, work.g_x, work.g_y, work.g_w, work.g_h,
  463.             &tmp.g_x, &tmp.g_y, &tmp.g_w, &tmp.g_h);
  464.     
  465.     return tmp;
  466. }
  467.  
  468.  
  469. ////////////////////////////////////////////////////////////////////////
  470. //
  471. // SPC:    SetInfoText(const char *line)
  472. //    -- store and set the new info line for the window
  473. //    -- this _must_! be at least created
  474. //
  475. ////////////////////////////////////////////////////////////////////////
  476.  
  477. void GEMwindow::SetInfoText(const char *line)
  478. {
  479.     if (handle) {
  480.         delete info;
  481.         info = new char[ strlen(line)+1 ];
  482.         info = strcpy(info, line);
  483.         if (IsCreated()) wind_set(handle, WF_INFO, info, 0, 0);
  484.  
  485.         Ensure(strcmp(info, line)==0);
  486.     }
  487. }
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497. ////////////////////////////////////////////////////////////////////////
  498. //
  499. // SPC:    UserFulled()
  500. //    -- usually called by an application manager, the default action
  501. //    -- is to toggle between two possible positions and sizes
  502. //
  503. ////////////////////////////////////////////////////////////////////////
  504.  
  505. void GEMwindow::UserFulled()
  506. {
  507.     Require(IsOpen());
  508.     if (!IsOpen()) return;
  509.     
  510.     if (Max==WorkRect())            // i.e., is fulled
  511.         SetWorkRect(storer);        // use stored value
  512.     else
  513.     {
  514.         storer = WorkRect();        // store actual rectangle
  515.         SetWorkRect(Max);
  516.     }
  517. }
  518.  
  519.  
  520.  
  521.  
  522. ////////////////////////////////////////////////////////////////////////
  523. //
  524. // SPC:    UserResized(int w, int h)
  525. //    -- this function may be redefined to align the new size, but
  526. //    -- here it does nothing else than to call the standard Resize()
  527. //    -- of a simple GEMwindow with the same values
  528. //
  529. ////////////////////////////////////////////////////////////////////////
  530.  
  531. void GEMwindow::UserResized(int w, int h)
  532. {
  533.     Resize(w, h);
  534. }
  535.  
  536.  
  537.  
  538. void GEMwindow::SetName(const char *newName)
  539. {    
  540.     delete name;
  541.     name = new char[ strlen(newName)+1 ];
  542.     name = strcpy(name, newName);
  543.     if (IsCreated())
  544.         wind_set(handle, WF_NAME, name, 0, 0);
  545. }
  546.  
  547.  
  548. ////////////////////////////////////////////////////////////////////////
  549. //
  550. // SPC:    Flush()
  551. //    -- this method will be called, if the user changed the state
  552. //    -- of a slider, e.g., by moving it; descendant classes may
  553. //    -- refine it, with the aim of a more efficient implementation
  554. //
  555. ////////////////////////////////////////////////////////////////////////
  556.  
  557. void GEMwindow::Flush()
  558. {
  559.     if (IsOpen())
  560.         RedrawOverlaps(WorkRect());
  561. }
  562.  
  563.  
  564. ////////////////////////////////////////////////////////////////////////
  565. //
  566. // SPC:    SetVisibleLines(int noOfLines)
  567. //    -- change the number of visible lines, this change will be
  568. //    -- flushed through to the GEM window
  569. //
  570. ////////////////////////////////////////////////////////////////////////
  571.  
  572. void GEMwindow::SetVisibleLines(int noOfLines)
  573. {
  574.     Require(noOfLines >= 0);
  575.     Require(noOfLines <= totalLines);
  576.     
  577.     visibleLines = noOfLines;
  578.     
  579.     if (actualTopLine > totalLines - visibleLines)
  580.         actualTopLine = totalLines - visibleLines;
  581.  
  582.     VAlignSlider();
  583.     VFlushSlider();
  584. }
  585.  
  586.  
  587. void GEMwindow::SetTotalLines(int noOfLines)
  588. {
  589.     Require(noOfLines >= 0);
  590.  
  591.     bool change = FALSE;
  592.  
  593.     totalLines = noOfLines;
  594.  
  595.     if (noOfLines < visibleLines)
  596.     {
  597.         visibleLines = totalLines;
  598.         change = TRUE;
  599.     }
  600.  
  601.     if (actualTopLine > totalLines - visibleLines)
  602.     {
  603.         actualTopLine = totalLines - visibleLines;
  604.         change = TRUE;
  605.     }
  606.  
  607.     VAlignSlider();
  608.     VFlushSlider();
  609.  
  610.     if (change)
  611.         Flush();
  612. }
  613.  
  614.  
  615.  
  616.  
  617. void GEMwindow::SetTopLine(int noOfLine)
  618. {
  619.     Require(noOfLine >= 0);
  620.     Require(noOfLine <= totalLines - visibleLines);
  621.     
  622.     if (actualTopLine != noOfLine)
  623.     {
  624.         actualTopLine = noOfLine;
  625.         
  626.         VAlignSlider();
  627.         VFlushSlider();
  628.         Flush();
  629.     }
  630. }
  631.  
  632.  
  633.  
  634.  
  635. ////////////////////////////////////////////////////////////////////////
  636. //
  637. // SPC:    VCalculateGEMvalues() and CalculateValues():
  638. //    -- use the members totalLines, visibleLines and
  639. //    -- actualTopLine to calculate the size and position of the GEM
  640. //    -- slider and vice versa;
  641. //
  642. ////////////////////////////////////////////////////////////////////////
  643.  
  644. void GEMwindow::VCalculateGEMvalues()
  645. {
  646.     if (totalLines > 0) {
  647.         vSize = 1000 * visibleLines / totalLines;
  648.  
  649.         if (totalLines == visibleLines)
  650.             vPosition = 1;
  651.         else
  652.             vPosition = actualTopLine * 1000 /
  653.                 (totalLines-visibleLines);
  654.     }
  655. }
  656.  
  657.  
  658.  
  659.  
  660. ////////////////////////////////////////////////////////////////////////
  661. //
  662. // SPC: VCalculateValues()
  663. //    -- that method converts the GEM representation of the slider
  664. //    -- into the document representation
  665. //
  666. ////////////////////////////////////////////////////////////////////////
  667.  
  668. void GEMwindow::VCalculateValues()
  669. {
  670.     // We shouldn't change visibleLines!  The user cannot manipulate the size of
  671.     // the slider knob anyway.
  672.     //
  673.     //visibleLines = vSize * totalLines / 1000;
  674.     
  675.     actualTopLine =
  676.         vPosition*(totalLines-visibleLines)/1000;
  677. }
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684. ////////////////////////////////////////////////////////////////////////
  685. //
  686. // SPC:    VFlushSlider()
  687. //    -- is the counterpart of Flush(),
  688. //    -- and is used to flush any changes in the internal slider
  689. //    -- representation through to GEM; it doesn't need to be redefined
  690. //
  691. ////////////////////////////////////////////////////////////////////////
  692.  
  693. void GEMwindow::VFlushSlider()
  694. {
  695.     if (handle) {
  696.         VCalculateGEMvalues();            // ensures correctness
  697.     
  698.         if (IsCreated()) {
  699.             wind_set(handle, WF_VSLIDE, vPosition, 0, 0, 0);
  700.             wind_set(handle, WF_VSLSIZE, vSize, 0, 0, 0);
  701.         }
  702.     }
  703. }
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712. ////////////////////////////////////////////////////////////////////////
  713. //
  714. // SPC:    VSlidered(int newPos)
  715. //    -- this function is called by the application manager, if
  716. //    -- the user has moved the vertical slide box to a new position;
  717. //    -- the default action performed by it is to store the new value,
  718. //    -- then to call VCalculateValues(), and then to return
  719. //    -- the value RedrawMe to the caller
  720. //
  721. ////////////////////////////////////////////////////////////////////////
  722.  
  723. GEMfeedback GEMwindow::VSlidered(int newPos)
  724. {
  725.     vPosition = newPos;
  726.     
  727.     VCalculateValues();
  728.  
  729.     VAlignSlider();            // let the client decide
  730.     VFlushSlider();
  731.     
  732.     return RedrawMe;
  733. }
  734.  
  735.  
  736.  
  737.  
  738.  
  739.  
  740. ////////////////////////////////////////////////////////////////////////
  741. //
  742. // SPC:    LineUp()
  743. //    -- this method will be called, if the user clicked the up arrow
  744. //    -- of the vertical slider, the result is a decraesed actualTopLine
  745. //    -- value and a redraw request
  746. //
  747. ////////////////////////////////////////////////////////////////////////
  748.  
  749. GEMfeedback GEMwindow::LineUp()
  750. {
  751.     if (actualTopLine > 0) {
  752.         actualTopLine--;
  753.         VAlignSlider();
  754.         VFlushSlider();
  755.         
  756.         return RedrawMe;
  757.     }
  758.     
  759.     return ContinueInteraction;
  760. }
  761.  
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769. ////////////////////////////////////////////////////////////////////////
  770. //
  771. // SPC:    LineDown()
  772. //    -- this method will be called, if the user clicked the down arrow
  773. //    -- of the vertical slider, the result is an incraesed actualTopLine
  774. //    -- value and a redraw request
  775. //
  776. ////////////////////////////////////////////////////////////////////////
  777.  
  778. GEMfeedback GEMwindow::LineDown()
  779. {
  780.     if (actualTopLine < totalLines - visibleLines) {
  781.         actualTopLine++;
  782.         VAlignSlider();
  783.         VFlushSlider();
  784.         
  785.         return RedrawMe;
  786.     }
  787.     
  788.     return ContinueInteraction;
  789. }
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796. ////////////////////////////////////////////////////////////////////////
  797. //
  798. // SPC:    PageUp() and PageDown()
  799. //    -- this methods (de|in)craese the actualTopLine value and change
  800. //    -- the contents of the window like in LineUp (Down)
  801. //
  802. ////////////////////////////////////////////////////////////////////////
  803.  
  804. GEMfeedback GEMwindow::PageUp()
  805. {
  806.     if (actualTopLine > 0) {
  807.         actualTopLine = (actualTopLine>=visibleLines)?
  808.                 actualTopLine-visibleLines : 0;
  809.         VAlignSlider();
  810.         VFlushSlider();
  811.         
  812.         return RedrawMe;
  813.     }
  814.     
  815.     return ContinueInteraction;        
  816. }
  817.  
  818.  
  819.  
  820.  
  821. GEMfeedback GEMwindow::PageDown()
  822. {
  823.     if (actualTopLine < totalLines - visibleLines) {
  824.         actualTopLine =
  825.             (actualTopLine+visibleLines
  826.                 > totalLines-visibleLines)?
  827.             totalLines-visibleLines :
  828.             actualTopLine+visibleLines;
  829.         VAlignSlider();
  830.         VFlushSlider();
  831.         
  832.         return RedrawMe;
  833.     }
  834.     
  835.     return ContinueInteraction;
  836. }
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845. ////////////////////////////////////////////////////////////////////////
  846. //
  847. // SPC:    VAlignSlider()
  848. //    -- this is a place holder for a function that may be redefined
  849. //    -- be any client class (or not), it is called after any change
  850. //    -- to the slider made by the user; when the member is executed,
  851. //    -- it should take the values of visibleLines,
  852. //    -- totalLines and actualTopLine as input and generate
  853. //    -- a new actualTopLine, e.g., align the top of a text line with
  854. //    -- the top line of the work area of the window; if any value of
  855. //    -- the slider representation changed, then TRUE should be returned
  856. //    -- to tell the called, that a redraw is needed
  857. //
  858. ////////////////////////////////////////////////////////////////////////
  859.  
  860. bool GEMwindow::VAlignSlider()
  861. {
  862.     // do nothing
  863.     
  864.     return FALSE;    // i.e., nothing changed, no redraw is needed
  865. }
  866.  
  867.  
  868.  
  869. ////////////////////////////////////////////////////////////////////////
  870. //
  871. // SPC:    SetVisibleColumns(int noOfLines)
  872. //    -- change the number of visible columns, this change will be
  873. //    -- flushed through to the GEM window
  874. //
  875. ////////////////////////////////////////////////////////////////////////
  876.  
  877. void GEMwindow::SetVisibleColumns(int noOfColumns)
  878. {
  879.     Require(noOfColumns >= 0);
  880.     Require(noOfColumns <= totalColumns);
  881.     
  882.     visibleColumns = noOfColumns;
  883.     
  884.     if (actualLeftColumn > totalColumns - visibleColumns)
  885.         actualLeftColumn = totalColumns - visibleColumns;
  886.     
  887.     HAlignSlider();
  888.     HFlushSlider();
  889. }
  890.  
  891.  
  892.  
  893. void GEMwindow::SetTotalColumns(int noOfColumns)
  894. {
  895.     Require(noOfColumns >= 0);
  896.     
  897.     bool change = FALSE;
  898.     
  899.     
  900.     totalColumns = noOfColumns;
  901.     
  902.     if (noOfColumns < visibleColumns) {
  903.         visibleColumns = totalColumns;
  904.         change = TRUE;
  905.     }
  906.     
  907.     if (actualLeftColumn > totalColumns - visibleColumns) {
  908.         actualLeftColumn = totalColumns - visibleColumns;
  909.         change = TRUE;
  910.     }
  911.     
  912.     HAlignSlider();
  913.     HFlushSlider();
  914.     
  915.     if (change)
  916.         Flush();
  917. }
  918.  
  919.  
  920.  
  921.  
  922. void GEMwindow::SetLeftColumn(int noOfColumn)
  923. {
  924.     Require(noOfColumn >= 0);
  925.     Require(noOfColumn <= totalColumns - visibleColumns);
  926.     
  927.     if (actualLeftColumn != noOfColumn) {
  928.         actualLeftColumn = noOfColumn;
  929.         
  930.         HAlignSlider();
  931.         HFlushSlider();
  932.         Flush();
  933.     }
  934. }
  935.  
  936.  
  937.  
  938.  
  939. ////////////////////////////////////////////////////////////////////////
  940. //
  941. // SPC:    HCalculateGEMvalues() and HCalculateValues():
  942. //    -- use the members totalColumns, visibleColumns and
  943. //    -- actualLeftColumn to calculate the size and position of the GEM
  944. //    -- slider and vice versa;
  945. //
  946. ////////////////////////////////////////////////////////////////////////
  947.  
  948. void GEMwindow::HCalculateGEMvalues()
  949. {
  950.     if (totalColumns>0) {
  951.         hSize = 1000 * visibleColumns / totalColumns;
  952.  
  953.         if (totalColumns == visibleColumns)
  954.             hPosition = 1;
  955.         else
  956.             hPosition = actualLeftColumn * 1000 /
  957.                 (totalColumns-visibleColumns);
  958.     }
  959. }
  960.  
  961.  
  962.  
  963.  
  964. ////////////////////////////////////////////////////////////////////////
  965. //
  966. // SPC: HCalculateValues()
  967. //    -- that method converts the GEM representation of the slider
  968. //    -- into the document representation
  969. //
  970. ////////////////////////////////////////////////////////////////////////
  971.  
  972. void GEMwindow::HCalculateValues()
  973. {
  974.     // We shouldn't change visibleColumns!  The user cannot manipulate the size of
  975.     // the slider knob anyway.
  976.     //
  977.     //visibleColumns = hSize * totalColumns / 1000;
  978.     
  979.     actualLeftColumn =
  980.         hPosition*(totalColumns-visibleColumns)/1000;
  981. }
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988. ////////////////////////////////////////////////////////////////////////
  989. //
  990. // SPC:    HFlushSlider()
  991. //    -- is the counterpart of GEMwindow::Flush(),
  992. //    -- and is used to flush any changes in the internal slider
  993. //    -- representation through to GEM; it doesn't need to be redefined
  994. //
  995. ////////////////////////////////////////////////////////////////////////
  996.  
  997. void GEMwindow::HFlushSlider()
  998. {
  999.     if (handle) {
  1000.         HCalculateGEMvalues();            // ensures correctness
  1001.     
  1002.         if (IsCreated()) {
  1003.             wind_set(handle, WF_HSLIDE, hPosition, 0, 0, 0);
  1004.             wind_set(handle, WF_HSLSIZE, hSize, 0, 0, 0);
  1005.         }
  1006.     }
  1007. }
  1008.  
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016. ////////////////////////////////////////////////////////////////////////
  1017. //
  1018. // SPC:    HSlidered(int newPos)
  1019. //    -- this function is called by the application manager, if
  1020. //    -- the user has moved the horizontal slide box to a new position;
  1021. //    -- the default action performed by it is to store the new value,
  1022. //    -- then to call HCalculateValues(), then to return the
  1023. //    -- value RedrawMe to the caller
  1024. //
  1025. ////////////////////////////////////////////////////////////////////////
  1026.  
  1027. GEMfeedback GEMwindow::HSlidered(int newPos)
  1028. {
  1029.     hPosition = newPos;
  1030.     
  1031.     HCalculateValues();
  1032.     
  1033.     HAlignSlider();            // let the client decide
  1034.     HFlushSlider();
  1035.     
  1036.     return RedrawMe;
  1037. }
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044. ////////////////////////////////////////////////////////////////////////
  1045. //
  1046. // SPC:    ColumnLeft()
  1047. //    -- this method will be called, if the user clicked the left arrow
  1048. //    -- of the horizontal slider, the result is a decraesed
  1049. //    -- actualLeftColumn value and a RedrawMe request to the caller
  1050. //
  1051. ////////////////////////////////////////////////////////////////////////
  1052.  
  1053. GEMfeedback GEMwindow::ColumnLeft()
  1054. {
  1055.     if (actualLeftColumn > 0) {
  1056.         actualLeftColumn--;
  1057.         HAlignSlider();
  1058.         HFlushSlider();
  1059.         
  1060.         return RedrawMe;
  1061.     }
  1062.     
  1063.     return ContinueInteraction;
  1064. }
  1065.  
  1066.  
  1067.  
  1068.  
  1069.  
  1070.  
  1071.  
  1072. ////////////////////////////////////////////////////////////////////////
  1073. //
  1074. // SPC:    ColumnRight()
  1075. //    -- this method will be called, if the user clicked the right arrow
  1076. //    -- of the horizontal slider, the result is an incraesed
  1077. //    -- actualLeftColumn value
  1078. //
  1079. ////////////////////////////////////////////////////////////////////////
  1080.  
  1081. GEMfeedback GEMwindow::ColumnRight()
  1082. {
  1083.     if (actualLeftColumn < totalColumns - visibleColumns) {
  1084.         actualLeftColumn++;
  1085.         HAlignSlider();
  1086.         HFlushSlider();
  1087.         
  1088.         return RedrawMe;
  1089.     }
  1090.     
  1091.     return ContinueInteraction;
  1092. }
  1093.  
  1094.  
  1095.  
  1096.  
  1097.  
  1098.  
  1099. ////////////////////////////////////////////////////////////////////////
  1100. //
  1101. // SPC:    PageLeft() and PageRight()
  1102. //    -- this methods (de|in)craese the actualLeftColumn value and change
  1103. //    -- the contents of the window like in ColumnLeft (Right)
  1104. //
  1105. ////////////////////////////////////////////////////////////////////////
  1106.  
  1107. GEMfeedback GEMwindow::PageLeft()
  1108. {
  1109.     if (actualLeftColumn > 0) {
  1110.         actualLeftColumn = (actualLeftColumn>=visibleColumns)?
  1111.             actualLeftColumn-visibleColumns : 0;
  1112.         HAlignSlider();
  1113.         HFlushSlider();
  1114.         
  1115.         return RedrawMe;
  1116.     }
  1117.     
  1118.     return ContinueInteraction;
  1119. }
  1120.  
  1121.  
  1122.  
  1123.  
  1124. GEMfeedback GEMwindow::PageRight()
  1125. {
  1126.     if (actualLeftColumn < totalColumns-visibleColumns) {
  1127.         actualLeftColumn =
  1128.             (actualLeftColumn+visibleColumns 
  1129.                 > totalColumns-visibleColumns) ?
  1130.             totalColumns - visibleColumns :
  1131.             actualLeftColumn + visibleColumns;
  1132.         HAlignSlider();
  1133.         HFlushSlider();
  1134.         
  1135.         return RedrawMe;
  1136.     }
  1137.     
  1138.     return ContinueInteraction;
  1139. }
  1140.  
  1141.  
  1142.  
  1143. ////////////////////////////////////////////////////////////////////////
  1144. //
  1145. // SPC:    HAlignSlider()
  1146. //    -- this is a place holder for a function that may be redefined
  1147. //    -- be any client class (or not), it is called after any change
  1148. //    -- to the slider made by the user; when the member is executed,
  1149. //    -- it should take the values of visibleColumns,
  1150. //    -- totalColumns and actualLeftColumn as input and generate
  1151. //    -- a new actualLeftColumn, e.g., align the left column of a text line 
  1152. //    -- with the beginning of the leftmost column of the work area of the
  1153. //    -- window
  1154. //
  1155. ////////////////////////////////////////////////////////////////////////
  1156.  
  1157. bool GEMwindow::HAlignSlider()
  1158. {
  1159.     return FALSE;
  1160. }
  1161.  
  1162. bool GEMwindow::IsOpen() const
  1163. {
  1164.     return created && opened;
  1165. }
  1166.