home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / elistb.zip / ELISTBOX.HPP < prev    next >
C/C++ Source or Header  |  1993-06-02  |  14KB  |  529 lines

  1. // $Header: h:/include/RCS/elistbox.hpp 1.3 93/06/02 16:01:17 Steve Exp $
  2.  
  3. //NOTE:  This code is UNSUPPORTED!  Mail will not be answered unless you are
  4. //     a "registered contributor".   Ypu can become a registered contributor
  5. //     by submitting a real bug (preferably with a fix) or a useful extension.
  6. //
  7. //     The author, for want of a more rational judge :-), will decide which
  8. //     bugs and extensions qualify.
  9. //
  10. //     After reading this message DO NOT DELETE IT, rather "comment it out" so
  11. //     that any line references will be consistent.
  12.  
  13. //  (C) Copyright Stephen B. Behman, 1993 -- All Rights Reserved
  14. //  You may modify and extend it but you may NOT SELL derivative works without
  15. //  the author's permission.
  16. //  It is not intended that this code be put into the Public Domain NOW,
  17. //  when the code is finished it will be.
  18.  
  19.  
  20. #ifndef __EXTENDED_LISTBOX__
  21. #define __EXTENDED_LISTBOX__
  22. #ifndef __OS2_H__
  23.  
  24. // PM includes
  25. #define INCL_PM
  26. #define INCL_WIN
  27. #include <os2.h>
  28. #endif
  29.  
  30. #ifndef ___SBB___
  31. #include <common.h>
  32. #endif
  33. #ifndef __stdlib_h
  34. #include <stdlib.h>
  35. #endif
  36.  
  37. #define NULLCOL ( Column* )0
  38.  
  39. class Column
  40.   {
  41.    protected:
  42.    char *head;
  43.    int startpos;
  44.    int width;
  45.    char *ptr;
  46.    int offset;
  47.    long justify;
  48.    public:
  49.    inline Column(char * h, int s, int w , char *p, int o=0, long j=DT_LEFT )
  50.        { head=h; startpos=s; width=w; ptr=p; offset=o; justify=j;}
  51.    void  drawheading( HPS ps, const RECTL& r )
  52.      {
  53.       RECTL t;
  54.       t.xLeft=r.xLeft+startpos*SysCharWidth;
  55.       t.xRight=r.xLeft+width*SysCharWidth;
  56.       t.yTop=r.yTop;
  57.       t.yBottom=r.yBottom;
  58.       WinDrawText( ps, -1, head, &t, SYSCLR_HELPTEXT , SYSCLR_ENTRYFIELD,
  59.            DT_CENTER | DT_TOP | DT_UNDERSCORE );
  60.       POINTL p;
  61.       p.x=t.xRight+SysCharWidth/2;
  62.       p.y=t.yTop;
  63.       GpiMove( ps, &p );
  64.       p.y=t.yBottom;
  65.       GpiLine( ps, &p );
  66.      }
  67.    virtual void draw( HPS ps, int ndx, const RECTL& r, int sel=0 )=0;
  68.    void setptr( char* p ){ ptr=p;}
  69.   };
  70.  
  71. class TextColumn : public Column
  72.   {
  73.    public:
  74.     inline TextColumn( char * h, int s, int w, char *tt, int i=4, long j=DT_LEFT )
  75.      : Column( h, s, w, tt, i, j ){}
  76.     void draw( HPS ps, int ndx, const RECTL& r, int sel=0 )
  77.       {
  78.        RECTL t;
  79.        t.yTop=r.yTop;
  80.        t.yBottom=r.yBottom;
  81.        t.xLeft=r.xLeft+startpos*SysCharWidth;
  82.        t.xRight=r.xLeft+width*SysCharWidth;
  83.        char * tch=ptr+ndx*offset;
  84.        WinDrawText( ps, -1, tch, &t, CLR_BLACK,
  85.             sel ? CLR_PALEGRAY : SYSCLR_ENTRYFIELD,
  86.             justify | DT_VCENTER );
  87.        POINTL p;
  88.        p.x=t.xRight+SysCharWidth/2;
  89.        p.y=t.yTop;
  90.        GpiMove( ps, &p );
  91.        p.y=t.yBottom;
  92.        GpiLine( ps, &p );
  93.       }
  94.   };
  95.  
  96. class CharColumn : public Column
  97.   {
  98.    public:
  99.     inline CharColumn( char * h, int s, int w, char *tt, int i=1,
  100.                long j=DT_CENTER ) : Column( h, s, w, tt, i, j ){}
  101.     void draw( HPS ps, int ndx, const RECTL& r, int sel=0 )
  102.       {
  103.        RECTL t;
  104.        t.yTop=r.yTop;
  105.        t.yBottom=r.yBottom;
  106.        t.xLeft=r.xLeft+startpos*SysCharWidth;
  107.        t.xRight=r.xLeft+width*SysCharWidth;
  108.        char * tch=ptr+ndx*offset;
  109.        WinDrawText( ps, 1, tch, &t, CLR_BLACK,
  110.             sel ? CLR_PALEGRAY : SYSCLR_ENTRYFIELD,
  111.             justify | DT_VCENTER );
  112.        POINTL p;
  113.        p.x=t.xRight+SysCharWidth/2;
  114.        p.y=t.yTop;
  115.        GpiMove( ps, &p );
  116.        p.y=t.yBottom;
  117.        GpiLine( ps, &p );
  118.       }
  119.   };
  120.  
  121. class TextPtrColumn : public Column
  122.   {
  123.    public:
  124.     inline TextPtrColumn( char * h, int s, int w, char **tt, int i=4, long j=DT_LEFT )
  125.      : Column( h, s, w, ( char*)tt, i, j ){}
  126.     void draw( HPS ps, int ndx, const RECTL& r, int sel=0 )
  127.       {
  128.        RECTL t;
  129.        t.yTop=r.yTop;
  130.        t.yBottom=r.yBottom;
  131.        t.xLeft=r.xLeft+startpos*SysCharWidth;
  132.        t.xRight=r.xLeft+width*SysCharWidth;
  133.        char * tch=*( char** )(ptr+ndx*offset);
  134.        WinDrawText( ps, -1, tch, &t, CLR_BLACK,
  135.             sel ? CLR_PALEGRAY : SYSCLR_ENTRYFIELD,
  136.             justify | DT_VCENTER );
  137.        POINTL p;
  138.        p.x=t.xRight+SysCharWidth/2;
  139.        p.y=t.yTop;
  140.        GpiMove( ps, &p );
  141.        p.y=t.yBottom;
  142.        GpiLine( ps, &p );
  143.       }
  144.   };
  145.  
  146. class LongColumn : public Column
  147.   {
  148.   public:
  149.  
  150.    LongColumn( char * h, int s, int w, long *tt, int i=4, long j=DT_RIGHT )
  151.           : Column( h, s, w, ( char * )tt, i, j ){}
  152.    void draw( HPS ps, int ndx, const RECTL& r, int sel=0 )
  153.      {
  154.       char tmp[30];
  155.       RECTL t;
  156.       t.yTop=r.yTop;
  157.       t.yBottom=r.yBottom;
  158.       t.xLeft=r.xLeft+startpos*SysCharWidth;
  159.       t.xRight=r.xLeft+width*SysCharWidth;
  160.       long  tch=*( long* )(ptr+ndx*offset);
  161.       ltoa( tch, tmp, 10 );
  162.       WinDrawText( ps, -1, tmp, &t, ( tch<0 ) ? CLR_RED : CLR_BLACK,
  163.            sel ? CLR_PALEGRAY : SYSCLR_ENTRYFIELD,
  164.            justify | DT_VCENTER );
  165.       POINTL p;
  166.       p.x=t.xRight+SysCharWidth/2;
  167.       p.y=t.yTop;
  168.       GpiMove( ps, &p );
  169.       p.y=t.yBottom;
  170.       GpiLine( ps, &p );
  171.      }
  172.   };
  173.  
  174. class MoneyColumn: public Column
  175.   {
  176.   public:
  177.     MoneyColumn( char * h, int s, int w, double *tt, int i=4, long j=DT_RIGHT )
  178.     : Column( h, s, w, ( char * )tt, i, j ){}
  179.    void draw( HPS ps, int ndx, const RECTL& r, int sel=0 )
  180.      {
  181.       int decimal;
  182.       int sign;
  183.       char prt[30];
  184.       char *tmp=prt;
  185.       RECTL t;
  186.       t.yTop=r.yTop;
  187.       t.yBottom=r.yBottom;
  188.       t.xLeft=r.xLeft+startpos*SysCharWidth;
  189.       t.xRight=r.xLeft+width*SysCharWidth;
  190.       double  tch=*( double* )(ptr+ndx*offset);
  191.  
  192.       char *str=fcvt( tch, 2, &decimal, &sign );
  193.       if( sign ) *(tmp++)='-';
  194.       if( decimal>0 )
  195.      while( (decimal--)>0 ) *(tmp++)=*(str++);
  196.       else *(tmp++)='0';
  197.       *(tmp++)='.';
  198.       *(tmp++)=decimal==0 ? *(str++) : '0';
  199.       *(tmp++)=*(str++);
  200.       *(tmp++)=0;
  201.       WinDrawText( ps, -1, prt, &t, ( sign ) ? CLR_RED : CLR_BLACK,
  202.            sel ? CLR_PALEGRAY : SYSCLR_ENTRYFIELD,
  203.            justify | DT_VCENTER );
  204.       POINTL p;
  205.       p.x=t.xRight+SysCharWidth/2;
  206.       p.y=t.yTop;
  207.       GpiMove( ps, &p );
  208.       p.y=t.yBottom;
  209.       GpiLine( ps, &p );
  210.      }
  211.   };
  212.  
  213. class Row
  214.   {
  215.   public:
  216.    Column **c;
  217.    long cnt;
  218.    inline Row( Column ** t , long i){c=t;cnt=i;}
  219.    inline Row( Row *t ){c=t->c;cnt=t->cnt;}
  220.    inline long count(  ){ return cnt;}
  221.    inline void show( const HPS ps, const int ndx, const RECTL& r, int sel=0 )
  222.      {
  223.       for( int i=0; c[i]!=NULL; i++ ) c[i]->draw( ps, ndx, r, sel );
  224.      }
  225.  
  226.    inline void drawheading( const HPS ps, const RECTL& r )
  227.      {
  228.  
  229.       for( int i=0; c[i]!=NULL; i++ )
  230.     c[i]->drawheading( ps, r );
  231.      }
  232.  
  233.   };
  234.  
  235. STDPROC( ExtendedListBoxProc );
  236. #define ELB_SELCHANGED WM_USER+1
  237. #define ELB_SEARCH     WM_USER+2
  238. #define ELB_DBLCLK     WM_USER+3
  239. #define ELB_ENTER      VK_ENTER
  240. #define WM_SETACTIVE   WM_USER+2
  241. class ExtendedListBox
  242.   {
  243.    Row& row;
  244.    long active;
  245.    long rows;
  246.    long top;
  247.    HWND scrollbar;
  248.    HWND parent;
  249.    long style;
  250.    long tot;
  251.    long& selected;
  252.    char *selvect;
  253.    ULONG id;
  254.    int scroll;
  255.    int old;
  256.   public:
  257.    ExtendedListBox( HWND Wnd, ULONG i, Row& rr, long& l, char* cp ):
  258.     row(rr),selected(l), selvect(cp)
  259.      {                      // find scrollbar and initialize it
  260.       tot=row.count();
  261.       id=i;
  262.       parent=WinQueryWindow( Wnd, QW_PARENT);
  263.       top=selected=active=0;
  264.       scroll=0;
  265.       HWND hEnum=WinBeginEnumWindows( Wnd );
  266.       do
  267.     {                  // look for V scroll bar
  268.      scrollbar=WinGetNextWindow( hEnum );
  269.      if( scrollbar )
  270.        {
  271.         ULONG ulStyle=WinQueryWindowULong( scrollbar, QWL_STYLE );
  272.         if ( ulStyle & SBS_VERT ) break;
  273.        }
  274.     }while ( scrollbar );
  275.       WinEndEnumWindows( hEnum );
  276.       FONTMETRICS fm;
  277.       HPS ps=WinGetPS( HWND_DESKTOP );      // Get handle to presentation space
  278.       GpiQueryFontMetrics( ps, (LONG) sizeof( FONTMETRICS ), &fm );
  279.       SysCharHeight=fm.lMaxBaselineExt;
  280.       SysCharWidth=fm.lAveCharWidth;
  281.       WinReleasePS(ps);           // Release the presentation space
  282.       SWP w;
  283.       WinQueryWindowPos( Wnd, &w );
  284.       rows=min(tot, w.cy/SysCharHeight-1);
  285.       WinSendMsg( scrollbar, SBM_SETSCROLLBAR, (MPARAM)0,
  286.           MPFROM2SHORT( 0, tot-1 ) );
  287.       WinEnableWindow( scrollbar, tot>rows ? TRUE : FALSE );
  288.      }
  289. //***
  290.    void paint( HWND Wnd, int outside=0 )
  291.     {
  292.      SWP sb;
  293.      WinQueryWindowPos( scrollbar, &sb );
  294.      SWP s;
  295.      WinQueryWindowPos( Wnd, &s );
  296.      HPS hps;
  297.      RECTL    r;
  298.      RECTL    rp;
  299.      r.xLeft=s.x;
  300.      r.xRight=s.x+s.cx-sb.cx+1;
  301.      r.yBottom=s.y+1;
  302.      r.yTop=s.y+s.cy;
  303.      hps=WinGetPS( parent );
  304.      if( old<top || old>=top+rows ) outside=1;
  305.      if( outside )
  306.        WinDrawBorder( hps, &r, 1, 1, CLR_BLACK,
  307.               SYSCLR_ENTRYFIELD, DB_STANDARD|DB_INTERIOR );
  308.      row.drawheading( hps, r);
  309.      rp=r;
  310.      r.yBottom=r.yTop-SysCharHeight;
  311.      if( scroll )
  312.        {
  313.         rp.yTop-=SysCharHeight;
  314.         WinScrollWindow( parent, 0, SysCharHeight*scroll, &rp, &rp,
  315.                  NULLHANDLE,( PRECTL )NULL,0 );
  316.         scroll=0;
  317.        }
  318.      for( int i=top; i < rows+top; i++)
  319.        {
  320.         r.yTop-=SysCharHeight;
  321.         r.yBottom-=SysCharHeight;
  322.         if( outside || i==old || i==active )
  323.           {
  324.            WinDrawBorder( hps, &r, 1, 0, CLR_BLACK,
  325.                   SYSCLR_ENTRYFIELD, DB_STANDARD|DB_INTERIOR );
  326.            if( (!selvect && i==selected ) || (selvect && selvect[i] ) )
  327.          {
  328.           WinFillRect( hps, &r, CLR_PALEGRAY );
  329.           WinDrawBorder( hps, &r, 1,0, CLR_BLACK, CLR_PALEGRAY, 0 );
  330.           row.show( hps, i, r, 0);
  331.          }
  332.            else
  333.           row.show( hps, i, r, 0);
  334.            if( i==active )
  335.          {
  336.           GpiSetLineType( hps, LINETYPE_DOT );
  337.           POINTL p={r.xLeft,r.yBottom };
  338.           GpiMove( hps, &p );
  339.           p.x=r.xRight-1;
  340.           GpiLine( hps, &p );
  341.           p.y=r.yTop-1;
  342.           GpiMove( hps, &p );
  343.           p.x=r.xLeft;
  344.           GpiLine( hps, &p );
  345.           GpiSetLineType( hps, LINETYPE_DEFAULT );
  346.          }
  347.           }
  348.        }
  349.      WinReleasePS( hps );
  350.     }
  351.  
  352. //***
  353.    void setselect( HWND Wnd  )
  354.      {
  355.       if( !selvect ) selected=active;
  356.       else
  357.     {
  358.      selvect[active]=( char )(!selvect[active]);
  359.      WinPostMsg( Wnd, WM_CONTROL, MPFROM2SHORT( id, ELB_SELCHANGED ),
  360.              ( MPARAM )active );
  361.     }
  362.      }
  363.  
  364. //***
  365.    void newactive( MPARAM mp2  )
  366.      {
  367.       old=active;
  368.       switch( S2(mp2) )
  369.     {
  370.      case SB_LINEUP:
  371.        active=max( active-1, 0 );
  372.        if( active<top )
  373.          {
  374.           top=active;
  375.           scroll=-1;
  376.          }
  377.        break;
  378.      case SB_LINEDOWN:
  379.        active=min( active+1, tot-1 );
  380.        if( active>top+rows-1 )
  381.          {
  382.           top=min( top+1, tot-rows );
  383.           scroll=1;
  384.          }
  385.        break;
  386.      case SB_PAGEUP:
  387.        active=max( top-1, 0 );
  388.        top=max( top-rows, 0 );
  389.        break;
  390.      case SB_PAGEDOWN:
  391.        active=min( top+rows, tot-1 );
  392.        top=min( top+rows, tot-rows );
  393.        break;
  394.      case SB_SLIDERPOSITION:
  395.      case SB_SLIDERTRACK:
  396.        active=S1(mp2);
  397.        if( active>top+rows-1 )top=min( active-rows+1, tot-rows );
  398.        else if( active<top ) top=active;
  399.        break;
  400.      case SB_ENDSCROLL:
  401.      break;
  402.     }
  403.       if( !selvect )selected=active;
  404.       WinSendMsg( scrollbar, SBM_SETSCROLLBAR, (MPARAM)active,
  405.           MPFROM2SHORT( 0, tot-1 ) );
  406.      }
  407.    friend STDPROC( ExtendedListBoxProc );
  408.   };
  409.  
  410.  
  411. //***
  412. void WinCreateELB( HWND Wnd, ULONG id, Row& rr, long& ll,
  413.            char* selp=( char * )NULL )
  414.   {
  415.    HWND elb= WinWindowFromID( Wnd, id );
  416.    WinSubclassWindow( elb, ( PFNWP )ExtendedListBoxProc);
  417.    ExtendedListBox * telb=( ExtendedListBox * )WinQueryWindowULong( elb, QWL_USER );
  418.    if( telb ) delete telb;
  419.    ExtendedListBox *t=new ExtendedListBox( elb, id, rr, ll, selp );
  420.    WinSendMsg( elb, WM_CREATE, ( MPARAM )t, 0 );
  421. //   WinSendMsg( elb, WM_PAINT, 0, 0 );
  422.   }
  423.  
  424.  
  425. STDPROC( ExtendedListBoxProc )
  426.   {
  427.    if( MSG == WM_CREATE )
  428.     {
  429.      WinSetWindowULong( Wnd, QWL_USER, ( ULONG )mp1 );
  430.      returnF;
  431.     }
  432.    ExtendedListBox *t=( ExtendedListBox* )WinQueryWindowULong( Wnd, QWL_USER );
  433.    HWND owner=WinQueryWindow( Wnd, QW_OWNER );
  434.    switch( MSG )
  435.      {
  436.       case WM_BUTTON1CLICK:
  437.     {
  438.      int k=S2(mp1),j=0;
  439.      SWP s;
  440.      WinQueryWindowPos( Wnd, &s );
  441.      for( long i=s.cy-2*SysCharHeight; i>0; i-=SysCharHeight, j++ )
  442.        if( k > i ) break;
  443.      t->newactive( MPFROM2SHORT( t->top+j, SB_SLIDERPOSITION ) );
  444.      t->setselect( owner );
  445.      t->paint( Wnd );
  446.      returnT;
  447.     }
  448. //***
  449.       case WM_SETACTIVE:
  450.       t->newactive( MPFROM2SHORT( S1( mp1 ), SB_SLIDERPOSITION )  );
  451.       t->paint( Wnd, 1 );
  452.       returnT;
  453.       case WM_BUTTON1DBLCLK:
  454.     WinPostMsg( owner, WM_CONTROL, MPFROM2SHORT( t->id, ELB_DBLCLK ),
  455.             ( MPARAM )t->active );
  456.     returnT;
  457.       case WM_SETFOCUS:
  458.     WinFocusChange( HWND_DESKTOP, t->scrollbar, FC_NOLOSEFOCUS );
  459.     returnT;
  460.       case WM_DESTROY:
  461.     delete t;
  462.     break;
  463. //***
  464.       case WM_CHAR:
  465.     {
  466.      long flags=S1( mp1 );
  467.      if( flags & KC_CHAR && !( flags & ( KC_KEYUP | KC_VIRTUALKEY ) ) )
  468.        {
  469.         WinPostMsg( owner, WM_CONTROL, MPFROM2SHORT( t->id, ELB_SEARCH ),
  470.             MPFROM2SHORT( t->active, S1( mp2 ) ) );
  471.         returnT;
  472.        }
  473.  
  474.      if( flags & KC_VIRTUALKEY && !( flags & KC_KEYUP ) )
  475.        {
  476.         switch( S2( mp2 ) )
  477.           {
  478.         case VK_UP:
  479.           t->newactive( MPFROM2SHORT(0, SB_LINEUP) );
  480.           break;
  481.         case VK_DOWN:
  482.           t->newactive( MPFROM2SHORT( 0, SB_LINEDOWN ) );
  483.           break;
  484.         case VK_PAGEUP:
  485.           t->newactive( MPFROM2SHORT( 0, SB_PAGEUP ) );
  486.           break;
  487.         case VK_PAGEDOWN:
  488.           t->newactive( MPFROM2SHORT( 0, SB_PAGEDOWN ) );
  489.           break;
  490.         case VK_END:
  491.           t->newactive( MPFROM2SHORT( t->tot-1, SB_SLIDERPOSITION ) );
  492.           t->paint( Wnd, 1 );
  493.           returnT;
  494.         case VK_HOME:
  495.           t->newactive( MPFROM2SHORT( 0, SB_SLIDERPOSITION )  );
  496.           t->paint( Wnd, 1 );
  497.           returnT;
  498.         case VK_SPACE:
  499.           t->setselect( owner );
  500.           break;
  501.         case VK_ENTER:
  502.         case VK_NEWLINE:
  503.           WinPostMsg( owner , WM_CONTROL, MPFROM2SHORT(t->id,ELB_ENTER),
  504.                   ( MPARAM )t->active );
  505.           returnT;
  506.         case VK_TAB:
  507.         case VK_BACKTAB:
  508.           returnDWP;
  509.         default:
  510.           returnF;
  511.           }
  512.         t->paint( Wnd );
  513.         returnT;
  514.        }
  515.      returnT;
  516.     }
  517.  
  518.       case WM_VSCROLL:
  519.     t->newactive( mp2 );
  520.     t->paint( Wnd );
  521.     break;
  522.       case WM_PAINT:
  523.     t->paint( Wnd, 1 );
  524.      }
  525.    returnDWP;
  526.   }
  527.  
  528. #endif
  529.