home *** CD-ROM | disk | FTP | other *** search
- //===============================================================
- // vCommandPane - the command bar pane class used by the vWindow class
- //
- // Copyright (C) 1995,1996,1997,1998 Bruce E. Wampler
- //
- // This file is part of the V C++ GUI Framework, and is covered
- // under the terms of the GNU Library General Public License,
- // Version 2. This library has NO WARRANTY. See the source file
- // vapp.cxx for more complete information about license terms.
- //===============================================================
- #include <v/vos2.h> // for OS/2 stuff
- #include <v/vcmdpane.h>
- #include <v/vwindow.h> // we are part of a window
- #include <v/vthislst.h> // For this list
-
- // Define static data of the class
- MRESULT EXPENTRY CPProcCB(HWND hDlg, ULONG uMsg, MPARAM mp1, MPARAM mp2);
-
- static vThisList _thisList; // hide this in this file
-
- //===================>>> vCommandPane::vCommandPane <<<====================
- vCommandPane::vCommandPane(CommandObject* cList) :
- vPane(P_Commands), vCmdParent(P_Commands)
- {
-
- SysDebug(Constructor,"vCommandPane::vCommandPane() constructor\n")
- _origList = cList; // handle to list of commands
- _dialogType = aCmdBar; // this is a command pane
- _isDisplayed = 1; // Command bars visible by default
- _cmdObj = 0; // no list
- _cmdObjCount = 0;
- _TextInActive = 0;
- }
-
- //===================>>> vCommandPane::vCommandPane <<<====================
- // Constructor for vStatus type status bars
- // the list of elements are assumed to be just text labels
- // implemented here as vBoxedLabels
-
- vCommandPane::vCommandPane(vStatus* s_bar) :
- vPane(P_Status), vCmdParent(P_Status)
- {
- _dialogType = aStatBar; // this is really a command pane
- _isDisplayed = 1; // Status bars visible by default
- char* cp;
- SysDebug(Constructor,"vStatusPane::vStatusPane() constructor\n")
-
- // get number of objects in pane
- for (_cmdObjCount = 1; s_bar[_cmdObjCount].label; ++_cmdObjCount);
-
- _cmdObj = new CommandObject[_cmdObjCount+1];
- for (int ix = 0; ix <= _cmdObjCount; ++ix)
- {
- if (!s_bar[ix].label) // end of list
- {
- _cmdObj[ix].cmdType = C_EndOfList;
- _cmdObj[ix].title = 0;
- break;
- }
- _cmdObj[ix].cmdType = C_BoxedLabel;
-
- _cmdObj[ix].cmdId = s_bar[ix].statId;
- _cmdObj[ix].Sensitive = s_bar[ix].sensitive;
- _cmdObj[ix].retVal = 0;
- cp = new char[strlen(s_bar[ix].label)+1]; // copy string
- strcpy(cp, s_bar[ix].label);
- _cmdObj[ix].title = cp;
- _cmdObj[ix].itemList = 0;
- _cmdObj[ix].attrs = s_bar[ix].attrs;
- _cmdObj[ix].cFrame = 0;
- _cmdObj[ix].cRightOf = 0;
- _cmdObj[ix].cBelow = 0;
- _cmdObj[ix].size = s_bar[ix].width;
- _cmdObj[ix].tip = 0;
- }
- _origList = _cmdObj; // handle to list of commands
- }
-
- //===================>>> vCommandPane::~vCommandPane <<<====================
- vCommandPane::~vCommandPane()
- {
- SysDebug(Destructor,"vCommandPane::~vCommandPane() destructor\n")
- // theApp->unregisterCmdPane(this);
- _parentWin->unregisterCmdPane(this); // vWindow is tracking pane
-
- if (_hTemplate !=0)
- {
- DosFreeMem(_hTemplate);
- _hTemplate = 0;
- }
- if (_cmdObj != 0)
- {
- for (int ix = 0 ; ix < _cmdObjCount ; ++ix)
- {
- if (_cmdObj[ix].title)
- delete [] _cmdObj[ix].title; // free strings
- }
- delete [] _cmdObj; // free list
- }
- _thisList.Delete((ThisId)_barHwnd); // free the this ptr
- }
-
- //==================>>> vCommandPane::ProcessCmd <<<=======================
- void vCommandPane::ProcessCmd(ItemVal id, ItemVal rv, CmdType ct)
- {
- // simple interface between command objects and the
- // inherited vCmdParent ProcessCmd to the CommandObject which does the work
- _parentWin->WindowCommand(id, rv, ct);
- }
- //====================>>> vCommandPane::GetPaneValue <<<======================
- int vCommandPane::GetPaneValue(ItemVal id, int& val) VCONST
- {
- if (HasId(id)) // make sure the id is in the pane
- {
- val = GetValue(id);
- return 1; // assume 0 if not found
- }
- else
- return 0; // can't find this id
- }
- //===================>>> vCommandPane::SetPaneValue <<<========================
- void vCommandPane::SetPaneValue(ItemVal id, int val, ItemSetType setType)
- {
- SetValue(id,val,setType);
- }
-
- //====================>>> vCommandPane::SetPaneString <<<======================
- void vCommandPane::SetPaneString(ItemVal id, VCONST char* str)
- {
- SetString(id,str);
- }
- //====================>>> vCommandPane::ShowPane <<<======================
- void vCommandPane::ShowPane(int OnOrOff) VCONST
- {
- if (OnOrOff != _isDisplayed) // only need to do something if changed
- {
- _isDisplayed = OnOrOff;
-
- if (_isDisplayed)
- {
- WinShowWindow (_barHwnd, TRUE);
- _parentWin->_numPanes++;
- }
- else
- {
- WinShowWindow (_barHwnd, FALSE);
- _parentWin->_numPanes--;
- }
- _parentWin->AdjustSize(this);
- }
- }
- //====================>>> vCommandPane::initialize <<<=======================
- void vCommandPane::initialize(vWindow* pWin, HWND hOwner)
- {
- // now, build the menu items in the widget provided
- DlgCmdList* curCmd;
-
- vPane::initialize(pWin, hOwner); // initialize base class
- _hOwner = hOwner;
- // Now, build the initial in-memory dialog template using
- // OS/2 Dialog template handle _hTemplate.
-
- // Using 8,helv makes it ok to use 8 in calculating control sizes!
- PPElement PPel[] = { {PP_FONTNAMESIZE,(ULONG) "8.Helv"}, {0}};
-
- // int buildOK = CreateDlgTemplate(FCF_NOBYTEALIGN, WS_VISIBLE | WS_CLIPSIBLINGS,
- int buildOK = CreateDlgTemplate(FCF_NOBYTEALIGN, WS_CLIPSIBLINGS,
- 0,0, 0,0, 0, "", "", "", AssyPresParams(PPel) );
-
- if (!buildOK)
- vSysError("vDialog - Unable to build dialog template");
-
- int ix;
- // Add each control to the template via AddCmd
- for (ix = 0 ; _origList && (_origList[ix].cmdType != C_EndOfList) ; ++ix)
- {
- curCmd = new DlgCmdList; // get a new cell
- curCmd->nextDCL = _cmdList; // add in at front
- _cmdList = curCmd;
- curCmd->cmdP = 0; // not added yet
- curCmd->cmdP = AddCmd(&_origList[ix]);
- }
- DoneAddingControls(); // All finished adding controls
- // Now ready to create the dialog
-
- _barHwnd = WinCreateDlg(WinQueryWindow(hOwner, QW_PARENT), hOwner,
- (PFNWP) &CPProcCB, _hTemplate, (PVOID) this);
-
- SysDebug2(OS2Dev,"vCommandPane::initialize hOwner:%u _barHwnd:%u \n", hOwner, _barHwnd)
-
- if( _barHwnd)
- {
- _wDialog = _barHwnd;
- pWin->registerCmdPane(this); // if created ok, then register with vWindow
- pWin->AdjustSize(this); // resize the frame to accomodate pane
- }
-
- DosFreeMem(_hTemplate);
- _hTemplate = 0;
-
- }
- // ---------------------------------------------------------------------
- //====================>>> DlgProc <<<=======================
- MRESULT EXPENTRY CPProcCB(HWND hDlg, ULONG uMsg,
- MPARAM mp1, MPARAM mp2)
- {
- vCommandPane* useThis;
- if (uMsg == WM_INITDLG) // first time!
- {
- useThis = (vCommandPane*)mp2;
- _thisList.Add((ThisId)hDlg, (void*)useThis);
- }
- else
- useThis = (vCommandPane*)_thisList.GetThis((ThisId)hDlg);
-
- if (!useThis)
- return WinDefDlgProc(hDlg, uMsg, mp1, mp2);
-
- return (MRESULT) useThis->DynamicDlgProc(hDlg, uMsg, mp1, mp2);
- }
-
- //====================>>> vCommandPane::OnInitDialog <<<==================
- int vCommandPane::OnInitDialog(HWND hwnd, MPARAM mp1, MPARAM mp2)
- {
- // Changes here must have equivlalents in the vDialog.cpp code
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
- {
- vCmd* cp = cc->cmdP;
-
- // BEW - V 1.17 - Shouldn't have to do this, but the dynamic
- // dialog creation somehow replaces characters > 128 with _.
- // This fixes that problem.
-
- if ((cp->dlgCmd)->cmdType == C_BoxedLabel ||
- (cp->dlgCmd)->cmdType == C_Button ||
- (cp->dlgCmd)->cmdType == C_CheckBox ||
- (cp->dlgCmd)->cmdType == C_Label ||
- (cp->dlgCmd)->cmdType == C_RadioButton ||
- (cp->dlgCmd)->cmdType == C_TextIn)
- {
- cp->SetCmdStr((cp->dlgCmd)->title);
- }
- else if ((cp->dlgCmd)->cmdType == C_Text)
- {
- if (!(cp->dlgCmd)->itemList || (*(char *)(cp->dlgCmd)->itemList == 0))
- cp->SetCmdStr((cp->dlgCmd)->title);
- else
- cp->SetCmdStr((char*)(cp->dlgCmd)->itemList);
- }
-
- if ((cp->dlgCmd)->cmdType == C_CheckBox && (cp->dlgCmd)->retVal)
- cp->SetCmdVal(1,Checked);
-
- if ((cp->dlgCmd)->cmdType == C_RadioButton && (cp->dlgCmd)->retVal)
- cp->SetCmdVal(1,Checked);
-
- if ((cp->dlgCmd)->cmdType == C_BoxedLabel)
- cp->DRAWITEM((cp->dlgCmd)->cmdId, (OWNERITEM*) _barHwnd);
-
- if ((cp->dlgCmd)->cmdType == C_Text)
- cp->DRAWITEM((cp->dlgCmd)->cmdId, (OWNERITEM*) _barHwnd);
-
- if ((cp->dlgCmd)->cmdType == C_ToggleButton)
- cp->DRAWITEM((cp->dlgCmd)->cmdId, (OWNERITEM*) _barHwnd);
-
- if ((cp->dlgCmd)->cmdType == C_ToggleIconButton)
- cp->DRAWITEM((cp->dlgCmd)->cmdId, (OWNERITEM*) _barHwnd);
-
- if ((cp->dlgCmd)->cmdType == C_Icon)
- cp->DRAWITEM((cp->dlgCmd)->cmdId, (OWNERITEM*) _barHwnd);
-
- if ((cp->dlgCmd)->cmdType == C_Slider || (cp->dlgCmd)->cmdType == C_Spinner)
- cp->SetCmdVal(cp->GetCmdValue((cp->dlgCmd)->cmdId),Value);
-
- if ((cp->dlgCmd)->cmdType == C_ProgressBar)
- cp->SetCmdVal(cp->GetCmdValue((cp->dlgCmd)->cmdId),Value);
-
-
- if (!(cp->dlgCmd)->Sensitive) // Make insensitive if it was
- {
- cp->SetCmdVal(0,Sensitive);
- }
-
- if ((cp->dlgCmd)->attrs & CA_Hidden) // Hide it!
- {
- cp->SetCmdVal(1,Hidden);
- }
-
- if ((cp->dlgCmd)->cmdType == C_List
- || (cp->dlgCmd)->cmdType == C_ComboBox
- || (cp->dlgCmd)->cmdType == C_SComboBox
- || (cp->dlgCmd)->cmdType == C_Spinner
- || (cp->dlgCmd)->cmdType == C_SList )
- {
- int curval = cp->GetCmdValue((cp->dlgCmd)->cmdId);
- cp->SetCmdVal(curval,ChangeList);
- }
-
- if ((cp->dlgCmd)->cmdType == C_Icon || (cp->dlgCmd)->cmdType == C_Frame)
- {
- // cp->SetCmdVal(0,Sensitive); // Trick to avoid getting focus
- }
-
- // Now add ToolTip if it has a message
- if ((cp->dlgCmd)->tip && *(cp->dlgCmd)->tip)
- {
- /* ToolTips code not implemented in OS/2 yet. More effort needed!!!
- TOOLINFO ti;
- char *cc = (char*) &ti;
- int lim = sizeof (ti);
- for (int i = 0 ; i++ < lim ; *cc++ = 0)
- ;
- ti.cbSize = sizeof(ti);
- ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
- ti.hwnd = hwnd;
- ti.uId = (UINT)GetDlgItem(hwnd,(cp->dlgCmd)->cmdId);
- ti.lpszText = TEXT((cp->dlgCmd)->tip);
- SendMessage(hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti);
- */
- }
- }
-
- // _isShown = 1; // We will be shown now
- RECTL rc; // to get our size
- WinQueryWindowRect (_barHwnd, &rc); // the rect of the command bar
-
- _windowY = 0; // put pane at bottom for now
- _windowH = rc.yTop - rc.yBottom; // compute height
-
- // WinEnableWindow(_barHwnd, TRUE);
-
- return 0;
- }
- //====================>>> vCommandPane::OnEnable <<<==================
- void vCommandPane::OnEnable(HWND hwnd, BOOL fEnable)
- {
- WinEnableWindow (hwnd, fEnable);
- /*
- // Make all child windows have the same status as the dialog box.
- for (HWND hwndCtl = (HWND) WinQueryWindow (hwnd, QW_TOP); hwndCtl != NULLHANDLE ;
- hwndCtl = (HWND) WinQueryWindow (hwnd, QW_NEXT))
- {
- WinEnableWindow (hwndCtl, fEnable);
- }
- */
- }
-
- //====================>>> vCommandPane::OnPaint <<<==================
- int vCommandPane::OnPaint(HWND hwnd)
- {
- // Paint dividing lines around command/status bar
- RECTL rc, rcInner, rcGrip;
- POINTL pnt = {0,0};
- LINEBUNDLE ShadowPen, LightPen;
- int borderH, borderV;
- int gripPitch, frameV, frameH;
-
- borderH = WinQuerySysValue (HWND_DESKTOP, SV_CYBORDER);
- borderV = WinQuerySysValue (HWND_DESKTOP, SV_CXBORDER);
- frameV = 0; // space from edge of bar to frame boundary
- frameH = 1;
- gripPitch = 2; // pitch of grip ribs
-
- ShadowPen.lColor = SYSCLR_BUTTONDARK;
- ShadowPen.usMixMode = FM_OVERPAINT;
- ShadowPen.usType = LINETYPE_SOLID;
-
- LightPen.lColor = SYSCLR_BUTTONLIGHT;
- LightPen.usMixMode = FM_OVERPAINT;
- LightPen.usType = LINETYPE_SOLID;
-
- // begin painting here
- HPS hdc = WinBeginPaint (_barHwnd, NULLHANDLE, &rc);
- WinQueryWindowRect(_barHwnd, &rc);
- WinFillRect(hdc, &rc, SYSCLR_BUTTONMIDDLE);
-
- if (paneType() == P_Status) // Paint a status bar
- {
-
- rcInner.xLeft = rc.xLeft + frameH;
- rcInner.xRight = rc.xRight - frameH +1;
- rcInner.yBottom = rc.yBottom + frameV;
- // to make it look centered, we need to add the border thickness to the top
- rcInner.yTop = rc.yTop - frameV - 2*borderV;
- WinDrawBorder(hdc,
- &rcInner,
- borderV,
- borderH,
- SYSCLR_BUTTONMIDDLE,
- SYSCLR_BUTTONMIDDLE,
- DB_DEPRESSED);
-
- // Paint diagonal grip ribs on status pane
- // draw grip area rectangle
- rcGrip.xLeft = rcInner.xRight - 6*gripPitch;
- rcGrip.yBottom = rcInner.yBottom;
- rcGrip.xRight = rcInner.xRight;
- rcGrip.yTop = rcInner.yBottom + 6*gripPitch;
- WinFillRect(hdc, &rcGrip, SYSCLR_BUTTONMIDDLE);
- // WinFillRect(hdc, &rcGrip, CLR_GREEN);
-
- rcInner.xRight -= 1; // the drawing commands are inclusive
- // draw bottom hash
- pnt.x = rcInner.xRight -gripPitch;
- pnt.y = rcInner.yBottom;
- GpiSetAttrs(hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE, 0, &ShadowPen);
- GpiSetCurrentPosition (hdc, &pnt);
- pnt.x = rcInner.xRight;
- pnt.y = rcInner.yBottom +gripPitch;
- GpiLine (hdc, &pnt);
-
- GpiSetAttrs(hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE, 0, &LightPen);
- pnt.x = rcInner.xRight -2*gripPitch;
- pnt.y = rcInner.yBottom;
- GpiSetCurrentPosition (hdc, &pnt);
- pnt.x = rcInner.xRight;
- pnt.y = rcInner.yBottom +2*gripPitch;
- GpiLine (hdc, &pnt);
-
- // draw middle hash
- pnt.x = rcInner.xRight -3*gripPitch;
- pnt.y = rcInner.yBottom;
- GpiSetAttrs(hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE, 0, &ShadowPen);
- GpiSetCurrentPosition (hdc, &pnt);
- pnt.x = rcInner.xRight;
- pnt.y = rcInner.yBottom +3*gripPitch;
- GpiLine (hdc, &pnt);
-
- GpiSetAttrs(hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE, 0, &LightPen);
- pnt.x = rcInner.xRight -4*gripPitch;
- pnt.y = rcInner.yBottom;
- GpiSetCurrentPosition (hdc, &pnt);
- pnt.x = rcInner.xRight;
- pnt.y = rcInner.yBottom +4*gripPitch;
- GpiLine (hdc, &pnt);
-
- // draw top hash
- pnt.x = rcInner.xRight -5*gripPitch;
- pnt.y = rcInner.yBottom;
- GpiSetAttrs(hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE, 0, &ShadowPen);
- GpiSetCurrentPosition (hdc, &pnt);
- pnt.x = rcInner.xRight;
- pnt.y = rcInner.yBottom +5*gripPitch;
- GpiLine (hdc, &pnt);
-
- GpiSetAttrs(hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE, 0, &LightPen);
- pnt.x = rcInner.xRight -6*gripPitch;
- pnt.y = rcInner.yBottom;
- GpiSetCurrentPosition (hdc, &pnt);
- pnt.x = rcInner.xRight;
- pnt.y = rcInner.yBottom +6*gripPitch;
- GpiLine (hdc, &pnt);
- }
- else // Paint a command bar
- {
- GpiSetCurrentPosition (hdc, &pnt);
-
- GpiSetAttrs(hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE, 0, &ShadowPen);
-
- pnt.x = rc.xRight;
- pnt.y = 0;
- GpiLine (hdc, &pnt);
-
- GpiSetAttrs(hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE, 0, &LightPen);
-
- pnt.x = 0;
- pnt.y = _windowH - borderH;
- GpiSetCurrentPosition (hdc, &pnt);
-
- pnt.x = rc.xRight;
- pnt.y = _windowH - borderH;
- GpiLine (hdc, &pnt);
-
- }
- WinEndPaint (hdc);
-
- return 0;
- }
-
- //====================>>> vCommandPane::OnCommand <<<==================
- void vCommandPane::OnCommand (vCmd *UseThis, int uMsg, MPARAM mp1,
- MPARAM mp2)
- {
- // A very dangerous thing can happen here if the button causes
- // vApp::Exit to be called. This can cause things to be destructed,
- // which means that the command object goes away, which means
- // that UseThis no longer points to something valid, which is of
- // course a problem. Exit can get called in CmdCallback, so we
- // will remember the command type first for the test after the call.
-
- CmdType ct = (UseThis->dlgCmd)->cmdType; // will be ok still
- UseThis->CmdCallback(uMsg, mp1, mp2);
-
- // We need a SetFocus to get the focus back to the
- // canvas so that cursor will work, but for
- // lists and combos, SetFocus breaks them. Also, we don't
- // want timer updates to text controls to cause focus grabbing
- // so we have to check for them too.
- if ((ct == C_ComboBox || ct == C_SComboBox) && SHORT2FROMMP(mp1) != CBN_ENTER)
- return;
-
- if ((ct == C_List || ct == C_SList)
- && SHORT2FROMMP(mp1) != LN_ENTER && SHORT2FROMMP(mp1) != LN_SELECT)
- return;
-
- if (ct == C_BoxedLabel || ct == C_ColorLabel || ct == C_Label || ct == C_ProgressBar
- || ct == C_Text || ct == C_Icon)
- {
- return;
- }
-
- // we need to flag when the user is inputing data into a text in box
- // so that we can know not to mess with the focus when the mouse
- // buttons are being clicked
- if (ct == C_TextIn)
- {
- if (SHORT2FROMMP(mp1) == EN_SETFOCUS)
- _TextInActive = 1;
- else if(SHORT2FROMMP(mp1) == EN_KILLFOCUS)
- _TextInActive = 0;
- return;
- }
-
- // The idea here is that we change the focus back to the client after
- // any WM_CONTROL/WM_COMMAND message occurs, but we only do this if the
- // app is currently active. If it is not, then we do nothing which prevents
- // automatic timer updates of things like text boxes from yanking away focus
- // from another app that is curently active.
- // note: parent of cmdpane should be our frame
- if ( WinQueryActiveWindow(HWND_DESKTOP) == WinQueryWindow(_barHwnd, QW_PARENT) )
- {
- WinFocusChange(HWND_DESKTOP, WinQueryWindow(_barHwnd, QW_OWNER),
- FC_NOSETACTIVE | FC_NOSETSELECTION);
- }
- }
-
- //====================>>> vCommandPane::DynamicDlgProc <<<==================
- int vCommandPane::DynamicDlgProc(HWND hDlg, UINT uMsg,MPARAM mp1, MPARAM mp2)
- {
- switch (uMsg)
- {
- case WM_INITDLG:
- _barHwnd = hDlg;
- _wDialog = hDlg; // used by vCmdParent
- return OnInitDialog(hDlg, mp1, mp2);
-
- /*
- case WM_ENABLE:
- OnEnable(hDlg, (BOOL) SHORT1FROMMP(mp1));
- break;
- */
- case WM_PAINT:
- return OnPaint(hDlg);
-
- case WM_CONTROL:
- case WM_COMMAND:
- {
- vCmd* UseThis = (vCmd *) getThisFromId((ItemVal)SHORT1FROMMP(mp1));
- if (!UseThis)
- {
- return 0;
- }
- OnCommand(UseThis, uMsg, mp1, mp2);
- return 0;
- }
-
- // we need to monitor if the cmdpane gets focus and then send the
- // focus right back to the client
- case WM_BUTTON1UP:
- case WM_BUTTON2UP:
- case WM_BUTTON3UP:
- case WM_CONTEXTMENU:
- case WM_BEGINSELECT:
- case WM_SINGLESELECT:
- {
- // if the user is inputing text into a textin box, then we
- // don't want to mess with the focus when user clicks the mouse
- // in the command bar (yes, it's a kludge!!!)
- if (_TextInActive == 1)
- return 0;
-
- WinFocusChange(HWND_DESKTOP, WinQueryWindow(_barHwnd ,QW_OWNER),
- FC_NOSETACTIVE | FC_NOSETSELECTION);
- break;
- }
-
- default:
- break;
- }
- return (int) WinDefDlgProc(hDlg, uMsg, mp1, mp2);
- }
-
-