pwlib.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:50k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * pwlib.cxx
  3.  *
  4.  * GUI classes.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: pwlib.cxx,v $
  30.  * Revision 1.82  2000/04/28 06:59:14  robertj
  31.  * Fixed race condition causing asserts in ballon help.
  32.  *
  33.  * Revision 1.81  2000/03/04 13:08:35  robertj
  34.  * Moved common function in open file dialog to common source file.
  35.  *
  36.  * Revision 1.80  1999/11/01 00:07:58  robertj
  37.  * Changed semantics of OnClose() to be the same as PTitledWindow
  38.  *
  39.  * Revision 1.79  1999/08/07 07:13:23  robertj
  40.  * Fixed problems with "balloon help" text popup.
  41.  *
  42.  * Revision 1.78  1999/03/29 03:39:55  robertj
  43.  * Changed semantics of PTitledWindow::OnClose() function.
  44.  *
  45.  * Revision 1.77  1999/03/09 10:30:19  robertj
  46.  * Fixed ability to have PMEMORY_CHECK on/off on both debug/release versions.
  47.  *
  48.  * Revision 1.76  1998/12/02 03:50:11  robertj
  49.  * Unix compatibility changes
  50.  *
  51.  * Revision 1.75  1998/12/01 13:01:10  robertj
  52.  * new directory structure.
  53.  * Unix version
  54.  *
  55.  * Revision 1.74  1998/12/01 11:41:49  craigs
  56.  * Remove warnings under GCC
  57.  *
  58.  * Revision 1.73  1998/10/15 11:32:52  robertj
  59.  * New memory leak detection system.
  60.  *
  61.  * Revision 1.72  1998/10/13 14:06:37  robertj
  62.  * Complete rewrite of memory leak detection code.
  63.  *
  64.  * Revision 1.71  1998/09/23 06:29:54  robertj
  65.  * Added open source copyright license.
  66.  *
  67.  * Revision 1.70  1998/09/22 15:06:54  robertj
  68.  * Fixed confusion in Font Dialog, variable at different levels with same name.
  69.  *
  70.  * Revision 1.69  1998/09/14 12:43:27  robertj
  71.  * Fixed standard "about" dialog
  72.  *
  73.  * Revision 1.68  1997/04/27 05:50:22  robertj
  74.  * DLL support.
  75.  *
  76.  * Revision 1.67  1996/06/28 13:23:21  robertj
  77.  * Temporary disable of balloon help under NT until thread problem fixed.
  78.  *
  79.  * Revision 1.66  1996/06/03 09:59:30  robertj
  80.  * Fixed coordinate system for caret position.
  81.  *
  82.  * Revision 1.65  1996/04/30 12:33:56  robertj
  83.  * Changed "inPixels" boolean to enum for three coordinate systems.
  84.  *
  85.  * Revision 1.64  1996/01/28 02:52:06  robertj
  86.  * Added assert into all Compare functions to assure comparison between compatible objects.
  87.  *
  88.  * Revision 1.63  1995/12/23 03:42:30  robertj
  89.  * Changed version numbers.
  90.  *
  91.  * Revision 1.62  1995/12/10 11:41:44  robertj
  92.  * Changed default default OnAbout() function to have user specified dialog.
  93.  *
  94.  * Revision 1.61  1995/11/20 11:04:52  robertj
  95.  * Fixed bug in scrolling twice on scroll bar click.
  96.  *
  97.  * Revision 1.60  1995/10/14 15:10:14  robertj
  98.  * Added function to update all control values from data pointers.
  99.  *
  100.  * Revision 1.58  1995/08/24 12:37:04  robertj
  101.  * Added standard colours for balloon help windows.
  102.  * Added UpdateCommandSources() to menu start selection.
  103.  *
  104.  * Revision 1.57  1995/08/12 22:34:48  robertj
  105.  * Changed balloon help font to something more portable.
  106.  * Added resID parameter passing to colour dialog Construct() function.
  107.  *
  108.  * Revision 1.56  1995/07/31 12:09:53  robertj
  109.  * Drag track documentation and semantic adjustment.
  110.  * Split off pop up window from balloon.
  111.  *
  112.  * Revision 1.55  1995/07/02 01:22:09  robertj
  113.  * Added drag tracking support.
  114.  * Moved function to .cxx file when fixed bug.
  115.  *
  116.  * Revision 1.54  1995/06/04 12:42:25  robertj
  117.  * Redesign of caret driver functions (made a lot more common).
  118.  * Fixed order of initialisers for GNU.
  119.  *
  120.  * Revision 1.53  1995/04/25 11:11:40  robertj
  121.  * Moved functions to .cxx file to avoid triadic compiler problems.
  122.  * Fixed incorrect parameter on colour component virtual functions.
  123.  *
  124.  * Revision 1.52  1995/04/22 00:51:41  robertj
  125.  * Fixed bug in balloon help for balloon help in a balloon help interactor.
  126.  *
  127.  * Revision 1.51  1995/04/03 11:27:43  robertj
  128.  * Fixed balloon help window so doesn't flash main window.
  129.  *
  130.  * Revision 1.50  1995/04/02 09:27:32  robertj
  131.  * Added "balloon" help.
  132.  *
  133.  * Revision 1.49  1995/02/22 10:54:05  robertj
  134.  * Stopped memory leak by removing stupid mod.
  135.  * ./
  136.  *
  137.  * Revision 1.48  1995/02/22  10:50:38  robertj
  138.  * Changes required for compiling release (optimised) version.
  139.  *
  140.  * Revision 1.47  1995/02/19  04:14:38  robertj
  141.  * Changed font constructor to be more general PString.
  142.  * Added dynamically linked command processing.
  143.  * Added AllowClose() function for PTitledWindow descendents.
  144.  *
  145.  * Revision 1.46  1995/02/05  00:52:17  robertj
  146.  * Fixed default About box, using resource string and memory stats dump.
  147.  *
  148.  * Revision 1.45  1995/01/27  11:15:45  robertj
  149.  * Added description string.
  150.  * Changed face name strings to be caseless.
  151.  *
  152.  * Revision 1.44  1995/01/22  07:29:16  robertj
  153.  * Added font description string.
  154.  * Added font & colour standard dialogs.
  155.  *
  156.  * Revision 1.43  1995/01/21  05:16:27  robertj
  157.  * Modified ShowAll so PScrollable does not change show state of scroll bars..
  158.  *
  159.  * Revision 1.42  1995/01/18  09:03:18  robertj
  160.  * Fixed bug for having multiple top level windows and all closing application.
  161.  *
  162.  * Revision 1.41  1995/01/15  04:57:51  robertj
  163.  * Fixed global cursor set function.
  164.  * Added memory stats to default About box.
  165.  *
  166.  * Revision 1.40  1995/01/07  04:39:47  robertj
  167.  * Redesigned font enumeration code and changed font styles.
  168.  *
  169.  * Revision 1.39  1995/01/06  10:44:01  robertj
  170.  * Changed PRealFont usage from pointer to reference.
  171.  *
  172.  * Revision 1.38  1995/01/02  12:25:48  robertj
  173.  * Added global cursor setting for wait cursor.
  174.  *
  175.  * Revision 1.37  1994/12/21  11:54:21  robertj
  176.  * Documentation and variable normalisation.
  177.  * Fixed bad behaviour in closing PTopLevelWindow
  178.  *
  179.  * Revision 1.36  1994/12/17  01:22:35  robertj
  180.  * Changed semantics of file filering in standard file dialogs.
  181.  *
  182.  * Revision 1.35  1994/12/14  11:17:19  robertj
  183.  * Changed PDIMENSION to be unsigned causing untold number of changes.
  184.  *
  185.  * Revision 1.34  1994/11/19  00:04:38  robertj
  186.  * Removed variable argument list binding for menus and controls.
  187.  * Added clear standard colour.
  188.  *
  189.  * Revision 1.33  1994/11/01  11:56:18  robertj
  190.  * Rearranged stdarg stuff to get over compiler wierdness.
  191.  *
  192.  * Revision 1.32  1994/10/30  11:47:14  robertj
  193.  * Changed mechanism for doing notification callback functions.
  194.  *
  195.  * Revision 1.31  1994/10/24  00:05:46  robertj
  196.  * Fixed bug in dialogs not setting value of first control.
  197.  *
  198.  * Revision 1.30  1994/10/23  03:47:49  robertj
  199.  * Changed colours to have 8 bit components.
  200.  * Completed PScrollable implementation.
  201.  *
  202.  * Revision 1.29  1994/09/25  10:52:58  robertj
  203.  * Removed PNULL_MENU_NOTIFY
  204.  *
  205.  * Revision 1.28  1994/08/21  23:43:02  robertj
  206.  * Added delayed close of interactors to avoid the "delete this" problem.
  207.  *
  208.  * Revision 1.27  1994/08/01  03:41:24  robertj
  209.  * Use of PNEW instead of new for heap debugging. Need undef for Unix end.
  210.  *
  211.  * Revision 1.26  1994/07/27  05:58:07  robertj
  212.  * Synchronisation.
  213.  *
  214.  * Revision 1.25  1994/07/17  10:46:06  robertj
  215.  * Adjusted menu handling so can have orphan sub menus.
  216.  *
  217.  * Revision 1.24  1994/07/02  03:03:49  robertj
  218.  * Time interval and timer redesign.
  219.  *
  220.  * Revision 1.23  1994/06/25  11:55:15  robertj
  221.  * Unix version synchronisation.
  222.  *
  223.  * Revision 1.22  1994/04/20  12:17:44  robertj
  224.  * assert changes
  225.  *
  226.  * Revision 1.21  1994/04/03  08:34:18  robertj
  227.  * Added help and focus functionality.
  228.  *
  229.  * Revision 1.20  1994/04/01  14:04:23  robertj
  230.  * Added OnInit function to all modal dialogs.
  231.  *
  232.  * Revision 1.19  1994/03/07  07:47:00  robertj
  233.  * Major upgrade
  234.  *
  235.  * Revision 1.18  1994/01/03  04:42:23  robertj
  236.  * Mass changes to common container classes and interactors etc etc etc.
  237.  *
  238.  * Revision 1.17  1993/12/31  06:54:17  robertj
  239.  * Made inlines optional for debugging purposes.
  240.  * Added PImgIcon class.
  241.  *
  242.  * Revision 1.16  1993/12/29  04:41:26  robertj
  243.  * Mac port.
  244.  *
  245.  * Revision 1.15  1993/12/24  04:34:31  robertj
  246.  * G++ warning elimination.
  247.  *
  248.  * Revision 1.14  1993/12/24  04:20:52  robertj
  249.  * Mac CFront port.
  250.  *
  251.  * Revision 1.13  1993/12/16  09:22:11  robertj
  252.  * Fixed problems with callback function.
  253.  *
  254.  * Revision 1.12  1993/12/16  06:20:57  robertj
  255.  * Changes to callback function definition due to GCC.
  256.  *
  257.  * Revision 1.11  1993/12/15  21:10:10  robertj
  258.  * Use new function for container class reference count.
  259.  *
  260.  * Revision 1.10  1993/12/04  05:21:26  robertj
  261.  * Moved code from pwlib.inl to reduce its size.
  262.  *
  263.  * Revision 1.9  1993/12/01  16:09:05  robertj
  264.  * Windows NT port.
  265.  *
  266.  * Revision 1.8  1993/11/20  17:26:28  robertj
  267.  * PCanvasState class creation and integration.
  268.  * PPoint and PRect ancestror class becoming private.
  269.  * Shape classes implementation.
  270.  *
  271.  * Revision 1.7  1993/08/27  18:17:47  robertj
  272.  * Added canvas function for drawing bevelled 3D areas.
  273.  * Added timer support.
  274.  * Added group checking of menu items.
  275.  * Fixed some CFront compatibility problems.
  276.  *
  277.  * Revision 1.6  1993/08/24  00:27:59  robertj
  278.  * Rearrangement of pushbutton classes.
  279.  * Added Grey standard colour.
  280.  * Added inPixels parameter to the validate.invalidate functions.
  281.  *
  282.  * Revision 1.5  1993/08/21  17:09:50  robertj
  283.  * Added function to allow setting of menus whenever it is selected.
  284.  *
  285.  * Revision 1.4  1993/08/21  01:50:33  robertj
  286.  * Made Clone() function optional, default will assert if called.
  287.  *
  288.  * Revision 1.3  1993/08/21  01:07:35  robertj
  289.  * Fission of file into bars.cxx & control.cxx
  290.  *
  291.  * Revision 1.2  1993/08/20  21:26:09  robertj
  292.  * Number edit box common code added.
  293.  *
  294.  * Revision 1.7  1993/08/10  12:58:38  robertj
  295.  * Fixed bug in DrawString(), right adjusted text.
  296.  * Very small optimisation of PStringListBox DrawItem() function.
  297.  *
  298.  * Revision 1.6  1993/07/15  04:29:39  robertj
  299.  * Adjustments to the 3D shadowing effect on buttons/status bar etc.
  300.  *
  301.  * Revision 1.5  1993/07/14  12:41:52  robertj
  302.  * Fixed comment leader.
  303.  *
  304.  * Revision 1.4  1993/07/14  02:08:18  robertj
  305.  * Fixed header comment for RCS logs.
  306.  */
  307. #ifdef __GNUC__
  308. #pragma implementation "commands.h"
  309. #pragma implementation "scrollab.h"
  310. #pragma implementation "balloon.h"
  311. #endif
  312. #include <pwlib.h>
  313. class PAboutDialog : public PModalDialog
  314. {
  315.   PCLASSINFO(PAboutDialog, PModalDialog)
  316.   public:
  317.     PAboutDialog(PInteractor * parent, PRESOURCE_ID id)
  318.       : PModalDialog(parent, id)
  319.     {
  320.       ConstructEnd(id);
  321.       for (PINDEX i = 0; i < GetNumChildren(); i++) {
  322.         if (children[i].IsDescendant(PPushButton::Class())) {
  323.           SetStdButtons((PPushButton *)&children[i]);
  324.           break;
  325.         }
  326.       }
  327.     }
  328. };
  329. #define new PNEW
  330. //////////////////////////////////////////////////////////////////////////////
  331. // PKeyCode
  332. #if defined(_PKEYCODE)
  333. PObject * PKeyCode::Clone() const
  334. {
  335.   return new PKeyCode(value, modifiers);
  336. }
  337. PObject::Comparison PKeyCode::Compare(const PObject & obj) const
  338. {
  339.   PAssert(obj.IsDescendant(PKeyCode::Class()), PInvalidCast);
  340.   const PKeyCode & other = (const PKeyCode &)obj;
  341.   if (value == other.value && modifiers == other.modifiers)
  342.     return EqualTo;
  343.   return value < other.value ? LessThan : GreaterThan;
  344. }
  345. #endif
  346. //////////////////////////////////////////////////////////////////////////////
  347. // PColour
  348. #if defined(_PCOLOUR)
  349. PColour::PColour(BYTE r, BYTE g, BYTE b, BYTE a)
  350. {
  351.   component[RedComponent] = r;
  352.   component[GreenComponent] = g;
  353.   component[BlueComponent] = b;
  354.   component[AlphaComponent] = a;
  355. }
  356. PColour::PColour(StandardColours col)
  357. {
  358.   static BYTE stdCol[NumStandardColours][NumComponents] = {
  359.     { 0,    0,    0,    0xff }, // Black
  360.     { 0xff, 0,    0,    0xff }, // Red
  361.     { 0,    0xff, 0,    0xff }, // Green
  362.     { 0xff, 0xff, 0,    0xff }, // Yellow
  363.     { 0,    0,    0xff, 0xff }, // Blue
  364.     { 0xff, 0,    0xff, 0xff }, // Magenta
  365.     { 0,    0xff, 0xff, 0xff }, // Cyan
  366.     { 0xff, 0xff, 0xff, 0xff }, // White
  367.     { 0x40, 0x40, 0x40, 0xff }, // Grey
  368.     { 0x80, 0x80, 0x80, 0xff }, // Grey
  369.     { 0xC0, 0xC0, 0xC0, 0xff }, // Grey
  370.     { 0,    0,    0,    0    }  // Clear
  371.   };
  372.   PAssert(col < NumStandardColours, PInvalidParameter);
  373.   for (PINDEX i = 0; i < NumComponents; i++)
  374.     component[i] = stdCol[col][i];
  375. }
  376. PObject * PColour::Clone() const
  377. {
  378.   return new PColour(component[RedComponent],  component[GreenComponent],
  379.                      component[BlueComponent], component[AlphaComponent]);
  380. }
  381. PObject::Comparison PColour::Compare(const PObject & obj) const
  382. {
  383.   PAssert(obj.IsDescendant(PColour::Class()), PInvalidCast);
  384.   const PColour & other = (const PColour &)obj;
  385.   
  386.   for (PINDEX i = 0; i < NumComponents; i++)
  387.     if (component[i] != other.component[i])
  388.       return GreaterThan;
  389.   
  390.   return EqualTo;
  391. }
  392. PINDEX PColour::HashFunction() const
  393. {
  394.   
  395.   return (PINDEX)((component[RedComponent]^0x55) +
  396.                   (component[GreenComponent]^0xaa) +
  397.                   (component[BlueComponent]^0xc3))%51;
  398. }
  399. void PColour::SetRed(BYTE r)
  400. {
  401.   component[RedComponent] = r;
  402. }
  403. void PColour::SetGreen(BYTE g)
  404. {
  405.   component[GreenComponent] = g;
  406. }
  407. void PColour::SetBlue(BYTE b)
  408. {
  409.   component[BlueComponent] = b;
  410. }
  411. void PColour::SetAlpha(BYTE a)
  412. {
  413.   component[AlphaComponent] = a;
  414. }
  415. long PColour::GetDistance(const PColour & other) const
  416. {
  417.   long sum = 0;
  418.   for (PINDEX i = 0; i < AlphaComponent; i++)
  419.     sum += component[i]*other.component[i];
  420.   return sum;
  421. }
  422. #endif
  423. //////////////////////////////////////////////////////////////////////////////
  424. // PRealColour
  425. #if defined(_PREALCOLOUR)
  426. void PRealColour::SetRed(BYTE)
  427. {
  428.   PAssertAlways(PUnimplementedFunction);
  429. }
  430. void PRealColour::SetGreen(BYTE)
  431. {
  432.   PAssertAlways(PUnimplementedFunction);
  433. }
  434. void PRealColour::SetBlue(BYTE)
  435. {
  436.   PAssertAlways(PUnimplementedFunction);
  437. }
  438. void PRealColour::SetAlpha(BYTE)
  439. {
  440.   PAssertAlways(PUnimplementedFunction);
  441. }
  442. #endif
  443. //////////////////////////////////////////////////////////////////////////////
  444. // PFont
  445. #if defined(_PFONT)
  446. PFont::PFont(const PString & theFacename, PDIMENSION theSize, WORD theStyle)
  447.   : facename(theFacename)
  448. {
  449.   size = theSize;
  450.   styles = theStyle;
  451. }
  452. void PFont::Construct(const PCaselessString & fontDescription)
  453. {
  454.   size = 12;
  455.   styles = Regular;
  456.   PStringArray field = fontDescription.Tokenise(",");
  457.   switch (field.GetSize()) {
  458.     case 3 :
  459.       if (field[2].FindOneOf("Bb") != P_MAX_INDEX)
  460.         styles |= Bold;
  461.       if (field[2].FindOneOf("Ii") != P_MAX_INDEX)
  462.         styles |= Italic;
  463.       if (field[2].FindOneOf("Uu") != P_MAX_INDEX)
  464.         styles |= Underline;
  465.       // Then do next case
  466.     case 2 :
  467.       size = (PDIMENSION)field[1].AsInteger();
  468.       // Then do next case
  469.     case 1 :
  470.       facename = field[0];
  471.   }
  472. }
  473. PObject * PFont::Clone() const
  474. {
  475.   return new PFont(facename, size, styles);
  476. }
  477. PObject::Comparison PFont::Compare(const PObject & obj) const
  478. {
  479.   PAssert(obj.IsDescendant(PFont::Class()), PInvalidCast);
  480.   const PFont & other = (const PFont &)obj;
  481.   return size == other.size &&
  482.          styles == other.styles &&
  483.          facename == other.facename
  484.                ? EqualTo : GreaterThan;
  485. }
  486. PCaselessString PFont::GetDescription() const
  487. {
  488.   PString desc = facename + ',' + PString(PString::Unsigned, size);
  489.   if (styles != Regular)
  490.     desc += ',';
  491.   if (IsBold())
  492.     desc += 'B';
  493.   if (IsItalic())
  494.     desc += 'I';
  495.   if (IsUnderlined())
  496.     desc += 'U';
  497.   return desc;
  498. }
  499. #endif
  500. //////////////////////////////////////////////////////////////////////////////
  501. // PFontFamily
  502. #if defined(_PFONTFAMILY)
  503. PObject::Comparison PFontFamily::Compare(const PObject & obj) const
  504. {
  505.   PAssert(obj.IsDescendant(PFontFamily::Class()), PInvalidCast);
  506.   return facename.Compare(((const PFontFamily &)obj).facename);
  507. }
  508. #endif
  509. //////////////////////////////////////////////////////////////////////////////
  510. // PCaret
  511. #if defined(_PCARET)
  512. PObject::Comparison PCaret::Compare(const PObject & obj) const
  513. {
  514.   PAssert(obj.IsDescendant(PCaret::Class()), PInvalidCast);
  515.   return caretSize.Compare(((const PCaret &)obj).caretSize);
  516. }
  517. #endif
  518. //////////////////////////////////////////////////////////////////////////////
  519. // PInteractor
  520. #if defined (_PINTERACTOR)
  521. PRect PInteractor::GetDrawingBounds(CoordinateSystem coords) const
  522. {
  523.   return GetDimensions(coords);
  524. }
  525. BOOL PInteractor::IsChild(PInteractor * parent) const
  526. {
  527.   for (PINDEX i = 0; i < parent->GetNumChildren(); i++) {
  528.     if (&parent[i] == this)
  529.       return TRUE;
  530.   }
  531.   return FALSE;
  532. }
  533. void PInteractor::UpdateCommandSources()
  534. {
  535.   PInteractor * top = this;
  536.   while (top->GetParent() != NULL)
  537.     top = top->GetParent();
  538.   top->UpdateMyCommandSources();
  539. }
  540. void PInteractor::UpdateMyCommandSources()
  541. {
  542.   for (PINDEX i = 0; i < GetNumChildren(); i++)
  543.     children[i].UpdateMyCommandSources();
  544. }
  545. void PInteractor::SetAllCursors(const PCursor & newCursor)
  546. {
  547.   savedCursor = cursor;
  548.   SetCursor(newCursor);
  549.   switch (cursorMode) {
  550.     case UseCurrentCursor :
  551.       cursorMode = UseSetAllCursor;
  552.       break;
  553.     case UseParentCursor :
  554.       cursorMode = UseSetAllParentCursor;
  555.       break;
  556.     default :
  557.       return;
  558.   }
  559.   for (PINDEX i = 0; i < GetNumChildren(); i++)
  560.     children[i].SetAllCursors(newCursor);
  561. }
  562. void PInteractor::RestoreAllCursors()
  563. {
  564.   for (PINDEX i = 0; i < GetNumChildren(); i++)
  565.     children[i].RestoreAllCursors();
  566.   cursorMode = UseCurrentCursor;
  567.   SetCursor(savedCursor);
  568.   switch (cursorMode) {
  569.     case UseSetAllCursor :
  570.       cursorMode = UseCurrentCursor;
  571.       break;
  572.     case UseSetAllParentCursor :
  573.       cursorMode = UseParentCursor;
  574.       break;
  575.     default :
  576.       break;
  577.   }
  578. }
  579. void PInteractor::_SetCaretPos(PORDINATE x, PORDINATE y,
  580.                                CoordinateSystem coords)
  581. {
  582.   switch (coords) {
  583.     case LocalCoords :
  584.       caretPosition = PPoint(FromPixelsDX(x), FromPixelsDY(y));
  585.       break;
  586.     case PixelCoords :
  587.       caretPosition = PPoint(x, y);
  588.       break;
  589.     case ScreenCoords :
  590.       caretPosition = FromScreen(x, y, PixelCoords);
  591.   }
  592.   caret.SetPosition(this);
  593. }
  594. PPoint PInteractor::GetCaretPos(CoordinateSystem coords) const
  595. {
  596.   switch (coords) {
  597.     case LocalCoords :
  598.       return FromPixels(caretPosition);
  599.     case ScreenCoords :
  600.       return ToScreen(caretPosition, PixelCoords);
  601.     case PixelCoords:
  602.     default:
  603.       break;
  604.   }
  605.   return caretPosition;
  606. }
  607. void PInteractor::ShowCaret(BOOL show)
  608. {
  609.   caretVisible += show ? -1 : 1;
  610.   if (show && caretVisible == 0)
  611.     caret.Show(this);
  612.   else if (!show && caretVisible == 1)
  613.     caret.Hide(this);
  614. }
  615. void PInteractor::SetFocusInteractor(PInteractor * interactor)
  616. {
  617.   if (parent != NULL)
  618.     parent->SetFocusInteractor(interactor);
  619. }
  620. PInteractor * PInteractor::GetFocusInteractor() const
  621. {
  622.   return (parent != NULL) ? parent->GetFocusInteractor() : (PInteractor *)NULL;
  623. }
  624. PCanvas * PInteractor::StartMouseTrack(PInteractor * child, BOOL wantCanvas)
  625. {
  626.   PAssert(mouseTrackInteractor == NULL, "Starting new mouse track while tracking.");
  627.   mouseTrackInteractor = child;
  628.   if (wantCanvas) {
  629.     mouseTrackCanvas = new PDrawCanvas(this, TRUE, TRUE);
  630.     mouseTrackCanvas->SetPenMode(PCanvas::InvertDst);
  631.     mouseTrackCanvas->SetFillMode(PCanvas::InvertDst);
  632.   }
  633.   if (child != this)
  634.     GrabMouse();
  635.   return mouseTrackCanvas;
  636. }
  637. void PInteractor::OnMouseTrack(PCanvas *, const PPoint &, BOOL)
  638. {
  639. }
  640. void PInteractor::_OnMouseMove(PKeyCode button, const PPoint & where)
  641. {
  642.   if (mouseTrackInteractor == NULL)
  643.     OnMouseMove(button, where);
  644.   else {
  645.     if (HasMouse())
  646.       mouseTrackInteractor->OnMouseTrack(mouseTrackCanvas, where, FALSE);
  647.     else
  648.       _OnMouseUp(button, where);
  649.   }
  650.   owner->DoBalloonHelp(this);
  651. }
  652. void PInteractor::_OnMouseUp(PKeyCode button, const PPoint & where)
  653. {
  654.   if (mouseTrackInteractor == NULL)
  655.     OnMouseUp(button, where);
  656.   else {
  657.     mouseTrackInteractor->OnMouseTrack(mouseTrackCanvas, where, TRUE);
  658.     delete mouseTrackCanvas;
  659.     if (this != mouseTrackInteractor)
  660.       ReleaseMouse();
  661.     mouseTrackInteractor = NULL;
  662.     mouseTrackCanvas = NULL;
  663.   }
  664. }
  665. void PInteractor::OnStartInput()
  666. {
  667. }
  668. BOOL PInteractor::OnEndInput()
  669. {
  670.   return TRUE;
  671. }
  672. void PInteractor::OnControlNotify(PControl & control, int option)
  673. {
  674. #if defined (_PCONTROL)
  675.   control.TransferValue(option);
  676.   PNotifier callback = control.GetNotifier();
  677.   if (!callback.IsNULL())
  678.     callback(control, option);
  679. #endif
  680. }
  681. void PInteractor::OnSelectHelp()
  682. {
  683.   if (parent != NULL)
  684.     parent->OnSelectHelp();
  685. }
  686. PBalloon * PInteractor::OnBalloonHelp()
  687. {
  688.   return (parent != NULL) ? parent->OnBalloonHelp() : (PBalloon *)NULL;
  689. }
  690. void PInteractor::ShowAll()
  691. {
  692.   for (PINDEX i = 0; i < GetNumChildren(); i++)
  693.     children[i].ShowAll();
  694.   Show();
  695. }
  696. void PInteractor::AutoAdjustBounds(PRect & bounds, AutoAdjustType type)
  697. {
  698.   PDim dim = GetDimensions(PixelCoords);
  699.   PDIMENSION vsWidth = owner->GetVScrollWidth();
  700.   PDIMENSION hsHeight = owner->GetHScrollHeight();
  701.   PRect structure = GetStructureBounds(PixelCoords);
  702.   PDim extra = structure.Dimensions() - dim;
  703.   switch (type) {
  704.     case AdjustBounds :
  705.       SetPosition(bounds.Left(), bounds.Top(), TopLeftPixels, TopLeftPixels);
  706.       SetDimensions(bounds.Width()-extra.Width(),
  707.                                  bounds.Height()-extra.Height(), PixelCoords);
  708.       break;
  709.     case AdjustTop :
  710.       SetPosition(bounds.Left(), bounds.Top(), TopLeftPixels, TopLeftPixels);
  711.       SetDimensions(bounds.Width()-extra.Width(), dim.Height(), PixelCoords);
  712.       bounds.SetTop(bounds.Top() + dim.Height() + extra.Height());
  713.       break;
  714.     case AdjustBottom :
  715.       SetDimensions(bounds.Width()-extra.Width(), dim.Height(), PixelCoords);
  716.       bounds.SetBottom(bounds.Bottom() - dim.Height() - extra.Height());
  717.       SetPosition(bounds.Left(), bounds.Bottom(), TopLeftPixels,TopLeftPixels);
  718.       break;
  719.     case AdjustLeft :
  720.       SetPosition(bounds.Left(), bounds.Top(), TopLeftPixels, TopLeftPixels);
  721.       SetDimensions(dim.Width(), bounds.Height()-extra.Height(), PixelCoords);
  722.       bounds.SetLeft(bounds.Left() + dim.Width() + extra.Width());
  723.       break;
  724.     case AdjustRight :
  725.       SetDimensions(dim.Width(), bounds.Height()-extra.Height(), PixelCoords);
  726.       bounds.SetRight(bounds.Right() - dim.Width() - extra.Width());
  727.       SetPosition(bounds.Right(), bounds.Top(), TopLeftPixels, TopLeftPixels);
  728.       break;
  729.     case AdjustVScrollOnly :
  730.       SetDimensions(vsWidth, bounds.Height(), PixelCoords);
  731.       bounds.SetRight(bounds.Right() - vsWidth);
  732.       SetPosition(bounds.Right(), bounds.Top(), TopLeftPixels, TopLeftPixels);
  733.       break;
  734.     case AdjustHScrollOnly :
  735.       SetDimensions(bounds.Width(), hsHeight, PixelCoords);
  736.       bounds.SetBottom(bounds.Bottom() - hsHeight);
  737.       SetPosition(bounds.Left(), bounds.Bottom(), TopLeftPixels,TopLeftPixels);
  738.       break;
  739.     case AdjustVScrollBeforeHScroll :
  740.       SetDimensions(vsWidth, bounds.Height() - hsHeight, PixelCoords);
  741.       bounds.SetRight(bounds.Right() - vsWidth);
  742.       SetPosition(bounds.Right(), bounds.Top(), TopLeftPixels,TopLeftPixels);
  743.       break;
  744.     case AdjustHScrollAfterVScroll :
  745.       SetDimensions(bounds.Width(), hsHeight, PixelCoords);
  746.       bounds.SetBottom(bounds.Bottom() - hsHeight);
  747.       SetPosition(bounds.Left(), bounds.Bottom(), TopLeftPixels,TopLeftPixels);
  748.       break;
  749.   }
  750. }
  751. PORDINATE PInteractor::ToPixelsX(PORDINATE x) const
  752. {
  753.   return (PORDINATE)(((long)x*(PORDINATE)font.GetAvgWidth(TRUE)+2)/4);
  754. }
  755. PORDINATE PInteractor::ToPixelsY(PORDINATE y) const
  756. {
  757.   return (PORDINATE)(((long)y*(PORDINATE)font.GetHeight(TRUE)+4)/8);
  758. }
  759. PORDINATE PInteractor::FromPixelsX(PORDINATE x) const
  760. {
  761.   int fontScaleX = font.GetAvgWidth(TRUE);
  762.   return (PORDINATE)(((long)x*4+fontScaleX/2)/fontScaleX);
  763. }
  764. PORDINATE PInteractor::FromPixelsY(PORDINATE y) const
  765. {
  766.   int fontScaleY = font.GetHeight(TRUE);
  767.   return (PORDINATE)(((long)y*8+fontScaleY/2)/fontScaleY);
  768. }
  769. #endif
  770. //////////////////////////////////////////////////////////////////////////////
  771. // PInteractorLayout
  772. #if defined(_PINTERACTORLAYOUT)
  773. PControl * PInteractorLayout::GetControl(PRESOURCE_ID id)
  774. {
  775.   for (PINDEX i = 0; i < GetNumChildren(); i++) {
  776.     PInteractor & child = children[i];
  777.     if (child.IsDescendant(PControl::Class()) &&
  778.                                    ((PControl &)child).GetControlID() == id)
  779.       return (PControl *)&child;
  780.   }
  781.   return NULL;
  782. }
  783. void PInteractorLayout::SetFocusInteractor(PInteractor * interactor)
  784. {
  785.   focusInteractor = interactor;
  786. }
  787. PInteractor * PInteractorLayout::GetFocusInteractor() const
  788. {
  789.   return focusInteractor;
  790. }
  791. void PInteractorLayout::UpdateControls()
  792. {
  793.   for (PINDEX i = 0; i < GetNumChildren(); i++)
  794.     if (children[i].IsDescendant(PControl::Class()))
  795.       ((PControl &)children[i]).TransferValue(PControl::NotifyUpdate);
  796. }
  797. #endif
  798. //////////////////////////////////////////////////////////////////////////////
  799. // PDialog
  800. #if defined(_PDIALOG)
  801. void PDialog::Close()
  802. {
  803.   OnClose();
  804.   owner->DelayedCloseInteractor(this);
  805. }
  806. void PDialog::OnClose()
  807. {
  808. }
  809. void PDialog::OnOk()
  810. {
  811.   Close();
  812. }
  813. void PDialog::OnCancel()
  814. {
  815.   Close();
  816. }
  817. void PDialog::StdButtonPressed(PPushButton & button, INT)
  818. {
  819.   if (&button == ok)
  820.     OnOk();
  821.   else if (&button == help)
  822.     OnSelectHelp();
  823.   else
  824.     OnCancel();
  825. }
  826. void PDialog::SetStdButtons(PPushButton * okBtn,
  827.                                PPushButton * cancelBtn, PPushButton * helpBtn)
  828. {
  829.   if ((ok = okBtn) != NULL)
  830.     ok->SetNotifier(PCREATE_NOTIFIER(StdButtonPressed));
  831.   if ((cancel = cancelBtn) != NULL)
  832.     cancel->SetNotifier(PCREATE_NOTIFIER(StdButtonPressed));
  833.   if ((help = helpBtn) != NULL)
  834.     help->SetNotifier(PCREATE_NOTIFIER(StdButtonPressed));
  835. }
  836. #endif
  837. ///////////////////////////////////////////////////////////////////////////////
  838. // PFloatingDialog
  839. #if defined(_PFLOATINGDIALOG)
  840. PFloatingDialog::PFloatingDialog(PInteractor * parent)
  841.   : PDialog(parent)
  842. {
  843.   Construct();
  844. }
  845. PFloatingDialog::PFloatingDialog(PInteractor * parent, PRESOURCE_ID resID)
  846.   : PDialog(parent, resID)
  847. {
  848.   Construct();
  849. }
  850. #endif
  851. ///////////////////////////////////////////////////////////////////////////////
  852. // PModalDialog
  853. #if defined(_PMODALDIALOG)
  854. void PModalDialog::OnInit()
  855. {
  856.   UpdateControls();
  857.   Save();
  858. }
  859. void PModalDialog::OnOk()
  860. {
  861.   EndModal(TRUE);
  862. }
  863. void PModalDialog::OnCancel()
  864. {
  865.   Restore();
  866.   EndModal(FALSE);
  867. }
  868. void PModalDialog::Save()
  869. {
  870. }
  871. void PModalDialog::Restore()
  872. {
  873. }
  874. #endif
  875. //////////////////////////////////////////////////////////////////////////////
  876. // PFileDialog
  877. #if defined (_PFILEDIALOG)
  878. void PFileDialog::OnFileSelect(const PFilePath &)
  879. {
  880. }
  881. #endif
  882. //////////////////////////////////////////////////////////////////////////////
  883. // POpenFileDialog
  884. #if defined (_POPENFILEDIALOG)
  885. PINDEX POpenFileDialog::AddFileType(const PString & type)
  886. {
  887.   PINDEX i = fileTypes.GetSize();
  888.   fileTypes[i] = type;
  889.   return i;
  890. }
  891. BOOL POpenFileDialog::OnFilterFile(const PFilePath &)
  892. {
  893.   return TRUE;
  894. }
  895. #endif
  896. //////////////////////////////////////////////////////////////////////////////
  897. // PPrintDialog
  898. #ifdef _PPRINTDIALOG
  899. PPrintDialog::PPrintDialog(PInteractor * parent, PRESOURCE_ID resID)
  900.   : PModalDialog(parent, resID)
  901. {
  902.   Construct();
  903. }
  904. PPrintDialog::PPrintDialog(PInteractor * parent,
  905.                                   const PPrintInfo & info, PRESOURCE_ID resID)
  906.   : PModalDialog(parent, resID),
  907.     printInfo(info)
  908. {
  909.   Construct();
  910. }
  911. #endif
  912. //////////////////////////////////////////////////////////////////////////////
  913. // PPrinterSetupDialog
  914. #ifdef _PPRINTERSETUPDIALOG
  915. PPrinterSetupDialog::PPrinterSetupDialog(PInteractor * parent,
  916.                                                            PRESOURCE_ID resID)
  917.   : PPrintDialog(parent, resID)
  918. {
  919.   Construct();
  920. }
  921. PPrinterSetupDialog::PPrinterSetupDialog(PInteractor * parent,
  922.                                   const PPrintInfo & info, PRESOURCE_ID resID)
  923.   : PPrintDialog(parent, info, resID)
  924. {
  925.   Construct();
  926. }
  927. #endif
  928. //////////////////////////////////////////////////////////////////////////////
  929. // PPrintJobDialog
  930. #ifdef _PPRINTJOBDIALOG
  931. PPrintJobDialog::PPrintJobDialog(PInteractor * parent, PRESOURCE_ID resID)
  932.   : PPrintDialog(parent, resID)
  933. {
  934.   Construct();
  935. }
  936. PPrintJobDialog::PPrintJobDialog(PInteractor * parent,
  937.                                   const PPrintInfo & info, PRESOURCE_ID resID)
  938.   : PPrintDialog(parent, info, resID)
  939. {
  940.   Construct();
  941. }
  942. #endif
  943. //////////////////////////////////////////////////////////////////////////////
  944. // PFontDialog
  945. #ifdef _PFONTDIALOG
  946. PFontDialog::PFontDialog(PInteractor * parent,
  947.                                     PPrintCanvas * pCanvas, PRESOURCE_ID resID)
  948.   : PModalDialog(parent, resID),
  949.     selectedFont(owner->GetSystemFont()),
  950.     printerCanvas(pCanvas)
  951. {
  952.   Construct(resID);
  953. }
  954. PFontDialog::PFontDialog(PInteractor * parent,
  955.              const PFont & newFont, PPrintCanvas * pCanvas, PRESOURCE_ID resID)
  956.   : PModalDialog(parent, resID),
  957.     selectedFont(newFont),
  958.     printerCanvas(pCanvas)
  959. {
  960.   Construct(resID);
  961. }
  962. #endif
  963. //////////////////////////////////////////////////////////////////////////////
  964. // PColourDialog
  965. #ifdef _PCOLOURDIALOG
  966. PColourDialog::PColourDialog(PInteractor * parent, PRESOURCE_ID resID)
  967.   : PModalDialog(parent, resID)
  968. {
  969.   Construct(resID);
  970. }
  971. PColourDialog::PColourDialog(PInteractor * parent,
  972.                                 const PColour & newColour, PRESOURCE_ID resID)
  973.   : PModalDialog(parent, resID),
  974.     colour(newColour)
  975. {
  976.   Construct(resID);
  977. }
  978. #endif
  979. //////////////////////////////////////////////////////////////////////////////
  980. // PTitledWindow
  981. #if defined (_PTITLEDWINDOW)
  982. PDim PTitledWindow::GetMinSize(CoordinateSystem coords)
  983. {
  984.   if (coords != LocalCoords)
  985.     return minSize;
  986.   return FromPixels(minSize);
  987. }
  988. PDim PTitledWindow::GetMaxSize(CoordinateSystem coords)
  989. {
  990.   if (coords != LocalCoords)
  991.     return maxSize;
  992.   return ToPixels(maxSize);
  993. }
  994. PDim PTitledWindow::GetZoomSize(CoordinateSystem coords)
  995. {
  996.   if (coords != LocalCoords)
  997.     return zoomSize;
  998.   return ToPixels(zoomSize);
  999. }
  1000. void PTitledWindow::SetZoomSize(const PDim & dim, CoordinateSystem coords)
  1001. {
  1002.   if (coords != LocalCoords)
  1003.     zoomSize = dim;
  1004.   else
  1005.     zoomSize = ToPixels(dim);
  1006. }
  1007.   void PTitledWindow::SetFocusInteractor(PInteractor * interactor)
  1008. {
  1009.   focusInteractor = interactor;
  1010. }
  1011. PInteractor * PTitledWindow::GetFocusInteractor() const
  1012. {
  1013.   return focusInteractor;
  1014. }
  1015. void PTitledWindow::OnClose()
  1016. {
  1017. }
  1018. BOOL PTitledWindow::Close()
  1019. {
  1020.   if (!AllowClose(FALSE))
  1021.     return FALSE;
  1022.   owner->DelayedCloseInteractor(this);
  1023.   return TRUE;
  1024. }
  1025. BOOL PTitledWindow::AllowClose(BOOL)
  1026. {
  1027.   return TRUE;
  1028. }
  1029. #endif
  1030. //////////////////////////////////////////////////////////////////////////////
  1031. // PTopLevelWindow
  1032. #if defined (_PTOPLEVELWINDOW) && defined (_PMENUITEM)
  1033. BOOL PTopLevelWindow::Close()
  1034. {
  1035.   if (this != owner->GetWindow())
  1036.     return PTitledWindow::Close();
  1037.   if (!AllowClose(TRUE))
  1038.     return FALSE;
  1039.   PINDEX i;
  1040.   for (i = 0; i < GetNumChildren(); i++) {
  1041.     if (children[i].IsDescendant(PTitledWindow::Class()))
  1042.       if (!((PTitledWindow&)children[i]).AllowClose(TRUE))
  1043.         return FALSE;
  1044.   }
  1045.   for (i = 0; i < GetNumChildren(); i++) {
  1046.     if (children[i].IsDescendant(PTitledWindow::Class()))
  1047.       ((PTitledWindow&)children[i]).Close();
  1048.   }
  1049.   OnClose();
  1050.   owner->Terminate();
  1051.   return TRUE;
  1052. }
  1053. void PTopLevelWindow::UpdateMyCommandSources()
  1054. {
  1055.   if (menu != NULL)
  1056.     menu->UpdateMyCommandSources();
  1057.   PTitledWindow::UpdateMyCommandSources();
  1058. }
  1059. void PTopLevelWindow::OnMenuStartSelect()
  1060. {
  1061.   UpdateCommandSources();
  1062. }
  1063. void PTopLevelWindow::OnMenuItemSelect(PMenuItem & item)
  1064. {
  1065.   PNotifier notifier = item.GetNotifier();
  1066.   if (!notifier.IsNULL())
  1067.     notifier(item, 0);
  1068. }
  1069. #endif
  1070. ///////////////////////////////////////////////////////////////////////////////
  1071. // PMDIFrameWindow
  1072. #if defined(_PMDIFRAMEWINDOW)
  1073. PRect PMDIFrameWindow::GetDocumentArea(CoordinateSystem coords) const
  1074. {
  1075.   if (coords != LocalCoords)
  1076.     return documentArea;
  1077.   return FromPixels(documentArea);
  1078. }
  1079. #endif
  1080. ///////////////////////////////////////////////////////////////////////////////
  1081. // PBalloon
  1082. PBalloon::PBalloon(PInteractor * parent)
  1083.   : PPopUp(parent)
  1084. {
  1085.   Construct();
  1086. }
  1087. PBalloon::PBalloon(PInteractor * parent, const PString & text)
  1088.   : PPopUp(parent),
  1089.     balloonText(text)
  1090. {
  1091.   Construct();
  1092.   SetText(text);
  1093. }
  1094. void PBalloon::Construct()
  1095. {
  1096.   owner->DoBalloonHelp(this, 1); // Initialise the new balloon help window
  1097.   SetForegroundColour(owner->GetBalloonFgColour());
  1098.   SetBackgroundColour(owner->GetBalloonBkColour());
  1099.   SetFont(owner->GetBalloonFont());
  1100. }
  1101. void PBalloon::SetText(const PString & text)
  1102. {
  1103.   balloonText = text;
  1104.   PDrawCanvas canvas(this);
  1105.   SetDimensions(canvas.MeasureString(balloonText) + PDim(2, 2), LocalCoords);
  1106.   PDim myDim = GetDimensions(PixelCoords);
  1107.   PRect r = parent->GetStructureBounds(ScreenCoords);
  1108.   r.Offset(r.Width()/8, r.Height() + myDim.Height()/2);
  1109.   r.SetDimensions(myDim);
  1110.   PRect scr = owner->GetScreenRect();
  1111.   if (r.Right() > scr.Right())
  1112.     r.SetX(scr.Right() - r.Width());
  1113.   if (r.Bottom() > scr.Bottom())
  1114.     r.SetY(scr.Bottom() - r.Height());
  1115.   SetPosition(r.X(), r.Y(), TopLeftScreen, TopLeftScreen);
  1116.   Show();
  1117. }
  1118. void PBalloon::OnRedraw(PCanvas & canvas)
  1119. {
  1120.   canvas.DrawString(canvas.GetDrawingBounds(),
  1121.                         balloonText, PCanvas::Centred|PCanvas::CentreVertical);
  1122. }
  1123. ///////////////////////////////////////////////////////////////////////////////
  1124. // PScrollable & PScroller
  1125. #if defined(_PSCROLLABLE)
  1126. PScroller::PScroller(PInteractor * parent)
  1127.   : PInteractor(parent)
  1128. {
  1129.   vScroll = new PVerticalScrollBar(this, PCREATE_NOTIFIER(ScrollBarNotify), 0);
  1130.   vScroll->Show();
  1131.   hScroll = new PHorizontalScrollBar(this,PCREATE_NOTIFIER(ScrollBarNotify),0);
  1132.   hScroll->Show();
  1133. }
  1134. PScrollable & PScroller::GetContents()
  1135. {
  1136.   PINDEX num = GetNumChildren();
  1137.   while (num > 2) {
  1138.     num--;
  1139.     PInteractor & contents = children[num];
  1140.     if (contents.IsDescendant(PScrollable::Class()))
  1141.       return (PScrollable &)contents;
  1142.   }
  1143.   PAssertAlways("No scrollable window in scroller");
  1144.   return *(PScrollable *)this;
  1145. }
  1146. void PScroller::ShowAll()
  1147. {
  1148.   GetContents().Show();
  1149.   Show();
  1150. }
  1151. void PScroller::_SetDimensions(PDIMENSION width, PDIMENSION height,
  1152.                                CoordinateSystem coords)
  1153. {
  1154.   PInteractor::_SetDimensions(width, height, coords);
  1155.   PRect bounds(GetDimensions(PixelCoords));
  1156.   if (hScroll->IsVisible() && vScroll->IsVisible()) {
  1157.     vScroll->AutoAdjustBounds(bounds, AdjustVScrollBeforeHScroll);
  1158.     hScroll->AutoAdjustBounds(bounds, AdjustHScrollAfterVScroll);
  1159.   }
  1160.   else if (vScroll->IsVisible())
  1161.     vScroll->AutoAdjustBounds(bounds, AdjustVScrollOnly);
  1162.   else if (hScroll->IsVisible())
  1163.     hScroll->AutoAdjustBounds(bounds, AdjustHScrollOnly);
  1164.   PScrollable & contents = GetContents();
  1165.   contents.AutoAdjustBounds(bounds);
  1166.   contents.SetScrollRange(contents.GetScrollRange());
  1167. }
  1168. void PScroller::ScrollBarNotify(PScrollBar &, INT option)
  1169. {
  1170.   if (option != PScrollBar::StartTrack)
  1171.     GetContents().ScrollTo(hScroll->GetValue(), vScroll->GetValue());
  1172. }
  1173. PScrollable::PScrollable(PScroller * parent)
  1174.   : PInteractor(parent), scrollRange(0, 0, 10000, 10000), scaleFactor(1, 1)
  1175. {
  1176. }
  1177. PRect PScrollable::GetDrawingBounds(CoordinateSystem coords) const
  1178. {
  1179.   PRect r(scrollRange.Origin()*scaleFactor, scrollRange.Corner()*scaleFactor);
  1180.   if (coords != LocalCoords)
  1181.     return r;
  1182.   return FromPixels(r);
  1183. }
  1184. static void AdjustScrollBar(PORDINATE min, PORDINATE max, PORDINATE scale,
  1185.                                         PDIMENSION window, PScrollBar * scroll)
  1186. {
  1187.   int winSize = window/scale;
  1188.   int maxAdjusted = max - min - winSize;
  1189.   if (maxAdjusted < min)
  1190.     maxAdjusted = min;
  1191.   scroll->SetMinimum((PSCROLLBAR_VALUE)min);
  1192.   scroll->SetMaximum((PSCROLLBAR_VALUE)maxAdjusted);
  1193.   scroll->SetSmallNudge((PSCROLLBAR_VALUE)((winSize+9)/10));
  1194.   scroll->SetLargeNudge((PSCROLLBAR_VALUE)((winSize*9+9)/10));
  1195. }
  1196. void PScrollable::SetScrollRange(const PRect & rect)
  1197. {
  1198.   scrollRange = rect;
  1199.   PScroller * scroller = (PScroller *)GetParent();
  1200.   PDim dim = GetDimensions(PixelCoords);
  1201.   AdjustScrollBar(scrollRange.Left(), scrollRange.Right(),
  1202.                              scaleFactor.X(), dim.Width(),  scroller->hScroll);
  1203.   AdjustScrollBar(scrollRange.Top(), scrollRange.Bottom(),
  1204.                              scaleFactor.Y(), dim.Height(), scroller->vScroll);
  1205.   origin.SetX(scroller->hScroll->GetValue());
  1206.   origin.SetY(scroller->vScroll->GetValue());
  1207. }
  1208. void PScrollable::SetScaleFactor(const PPoint & scale)
  1209. {
  1210.   PAssert(scale.X() > 0 && scale.Y() > 0, PInvalidParameter);
  1211.   scaleFactor = scale;
  1212.   SetScrollRange(GetScrollRange());
  1213. }
  1214. void PScrollable::ScrollTo(const PPoint & newOrg)
  1215. {
  1216.   PPoint oldOrigin = origin;
  1217.   PScroller * scroller = (PScroller *)GetParent();
  1218.   PNotifier notifer = scroller->hScroll->GetNotifier();
  1219.   scroller->hScroll->SetNotifier(PNotifier());
  1220.   scroller->hScroll->SetValue((PSCROLLBAR_VALUE)newOrg.X());
  1221.   scroller->hScroll->SetNotifier(notifer);
  1222.   notifer = scroller->vScroll->GetNotifier();
  1223.   scroller->vScroll->SetNotifier(PNotifier());
  1224.   scroller->vScroll->SetValue((PSCROLLBAR_VALUE)newOrg.Y());
  1225.   scroller->vScroll->SetNotifier(notifer);
  1226.   origin.SetX(scroller->hScroll->GetValue());
  1227.   origin.SetY(scroller->vScroll->GetValue());
  1228.   OnScroll(oldOrigin - origin);
  1229. }
  1230. void PScrollable::OnScroll(const PPoint & scrollDelta)
  1231. {
  1232.   if (scrollDelta.X() == 0 && scrollDelta.Y() == 0)
  1233.     return;
  1234.   PDim dim = GetDimensions(PixelCoords);
  1235.   PPoint delta = scrollDelta * scaleFactor;
  1236.   if ((PDIMENSION)PABS(delta.X()) > dim.Width() ||
  1237.       (PDIMENSION)PABS(delta.Y()) > dim.Height()) {
  1238.     Invalidate();
  1239.     return;
  1240.   }
  1241.   PDrawCanvas canvas(this, TRUE);
  1242.   canvas.Scroll(delta, PRect(dim));
  1243.   if (delta.X() > 0)
  1244.     Invalidate(0, 0, (PDIMENSION)delta.X(), dim.Height(), PixelCoords);
  1245.   else if (delta.X() < 0) {
  1246.     PORDINATE x=(dim.Width()/scaleFactor.X()+scrollDelta.X())*scaleFactor.X();
  1247.     Invalidate(x, 0, dim.Width()-x, dim.Height(), PixelCoords);
  1248.   }
  1249.   if (delta.Y() > 0)
  1250.     Invalidate(0, 0, dim.Width(), (PDIMENSION)delta.Y(), PixelCoords);
  1251.   else if (delta.Y() < 0) {
  1252.     PORDINATE y=(dim.Height()/scaleFactor.Y()+scrollDelta.Y())*scaleFactor.Y();
  1253.     Invalidate(0, y, dim.Width(), dim.Height()-y, PixelCoords);
  1254.   }
  1255. }
  1256. #endif
  1257. ///////////////////////////////////////////////////////////////////////////////
  1258. // PMenuEntry
  1259. #if defined(_PMENUENTRY)
  1260. PMenuEntry::PMenuEntry()
  1261. {
  1262.   itsMenu = NULL;
  1263. }
  1264. PMenuEntry::PMenuEntry(PSubMenu & menu, PMenuEntry * before)
  1265. {
  1266.   itsMenu = &menu;
  1267.   if (before != NULL)
  1268.     itsMenu->entries.Insert(*before, this);
  1269.   else
  1270.     itsMenu->entries.Append(this);
  1271. }
  1272. PObject::Comparison PMenuEntry::Compare(const PObject & obj) const
  1273. {
  1274.   PAssert(obj.IsDescendant(PMenuEntry::Class()), PInvalidCast);
  1275.   const PMenuEntry & other = (const PMenuEntry &)obj;
  1276.   int myPosition = GetPosition();
  1277.   int otherPosition = other.GetPosition();
  1278.   if (itsMenu != other.itsMenu)
  1279.     return itsMenu->Compare(*other.itsMenu);
  1280.   if (myPosition > otherPosition)
  1281.     return GreaterThan;
  1282.   if (myPosition < otherPosition)
  1283.     return LessThan;
  1284.   return EqualTo;
  1285. }
  1286. PRootMenu * PMenuEntry::GetRootMenu() const
  1287. {
  1288.   PSubMenu * root = GetMenu();
  1289.   if (root != NULL) {
  1290.     while (root->GetMenu() != NULL)
  1291.       root = root->GetMenu();
  1292.     if (root->IsDescendant(PRootMenu::Class()))
  1293.       return (PRootMenu *)root;
  1294.   }
  1295.   return NULL;
  1296. }
  1297. BOOL PMenuEntry::IsMenuItemCheckGroup(const PMenuItem &) const
  1298. {
  1299.   return FALSE;
  1300. }
  1301. void PMenuEntry::UpdateMyCommandSources()
  1302. {
  1303.   // Do nothing
  1304. }
  1305. #endif
  1306. ///////////////////////////////////////////////////////////////////////////////
  1307. // PMenuItem
  1308. #if defined(_PMENUITEM)
  1309. PMenuItem::PMenuItem(PSubMenu & menu,
  1310.                                 const PString & itemName, PMenuEntry * before)
  1311.   : PMenuEntry(menu, before),
  1312.     name(itemName),
  1313.     checkPointer(NULL),
  1314.     notifyForStateUpdate(FALSE)
  1315. {
  1316.   Construct(TRUE);
  1317. }
  1318. PMenuItem::PMenuItem(PSubMenu & menu, const PString & itemName,
  1319.                       const PNotifier & func, BOOL update, PMenuEntry * before)
  1320.   : PMenuEntry(menu, before),
  1321.     name(itemName),
  1322.     callback(func),
  1323.     checkPointer(NULL),
  1324.     notifyForStateUpdate(update)
  1325. {
  1326.   Construct(TRUE);
  1327. }
  1328. PMenuItem::PMenuItem(PSubMenu & menu, const PString & itemName,
  1329.                      const PKeyCode & accel, const PNotifier & func,
  1330.                      BOOL update, PMenuEntry * before)
  1331.   : PMenuEntry(menu, before),
  1332.     name(itemName),
  1333.     callback(func),
  1334.     checkPointer(NULL),
  1335.     notifyForStateUpdate(update)
  1336. {
  1337.   accelerator = accel;
  1338.   Construct(TRUE);
  1339. }
  1340. PMenuItem::PMenuItem(PRESOURCE_ID newID,
  1341.                 PSubMenu & menu, const char * itemName, const PKeyCode & accel)
  1342.   : PMenuEntry(menu, NULL),
  1343.     name(itemName),
  1344.     accelerator(accel),
  1345.     checkPointer(NULL),
  1346.     notifyForStateUpdate(FALSE)
  1347. {
  1348.   menuID = newID;
  1349.   Construct(FALSE);
  1350. }
  1351. PMenuItem::~PMenuItem()
  1352. {
  1353.   PRootMenu * root = GetRootMenu();
  1354.   if (root != NULL)
  1355.     root->keyedItems.SetAt(menuID, NULL);
  1356. }
  1357. PString PMenuItem::GetString() const
  1358. {
  1359.   return name;
  1360. }
  1361. void PMenuItem::UpdateMyCommandSources()
  1362. {
  1363.   if (notifyForStateUpdate && !callback.IsNULL())
  1364.     callback(*this, TRUE);
  1365. }
  1366. BOOL PMenuItem::IsMenuItemCheckGroup(const PMenuItem & groupItem) const
  1367. {
  1368.   return groupItem.GetNotifier() == callback;
  1369. }
  1370. void PMenuItem::SetGroupCheck(PINDEX newItem)
  1371. {
  1372.   PINDEX i = GetPosition();
  1373.   PSubMenu & myMenu = *itsMenu;
  1374.   while (i > 0 && myMenu[i-1].IsMenuItemCheckGroup(*this))
  1375.     i--;
  1376.   PINDEX pos = i;
  1377.   while (i < myMenu.GetSize() && myMenu[i].IsMenuItemCheckGroup(*this)) {
  1378.     ((PMenuItem &)myMenu[i]).Check((i - pos) == (newItem - 1));
  1379.     i++;
  1380.   }
  1381. }
  1382. void PMenuItem::SetGroupCheck()
  1383. {
  1384.   PINDEX pos = GetPosition();
  1385.   PINDEX i = pos;
  1386.   PSubMenu & myMenu = *itsMenu;
  1387.   while (i > 0 && myMenu[i-1].IsMenuItemCheckGroup(*this))
  1388.     i--;
  1389.   while (i < myMenu.GetSize() && myMenu[i].IsMenuItemCheckGroup(*this)) {
  1390.     ((PMenuItem &)myMenu[i]).Check(i == pos);
  1391.     i++;
  1392.   }
  1393. }
  1394. PINDEX PMenuItem::GetGroupCheck() const
  1395. {
  1396.   PINDEX i = GetPosition();
  1397.   PSubMenu & myMenu = *itsMenu;
  1398.   while (i > 0 && myMenu[i-1].IsMenuItemCheckGroup(*this))
  1399.     i--;
  1400.   PINDEX pos = i;
  1401.   while (i < myMenu.GetSize() && myMenu[i].IsMenuItemCheckGroup(*this)) {
  1402.     if (((PMenuItem &)myMenu[i]).IsChecked())
  1403.       return i - pos + 1;
  1404.     i++;
  1405.   }
  1406.   return 0;
  1407. }
  1408. #endif
  1409. //////////////////////////////////////////////////////////////////////////////
  1410. // PMenuSeparator
  1411. #if defined(_PMENUSEPARATOR)
  1412. PString PMenuSeparator::GetString() const
  1413. {
  1414.   return "";
  1415. }
  1416. void PMenuSeparator::SetString(const PString &)
  1417. {
  1418. }
  1419. #endif
  1420. //////////////////////////////////////////////////////////////////////////////
  1421. // PSubMenu
  1422. #if defined(_PSUBMENU)
  1423. void PSubMenu::UpdateMyCommandSources()
  1424. {
  1425.   for (PINDEX i = 0; i < GetSize(); i++)
  1426.     entries[i].UpdateMyCommandSources();
  1427. }
  1428. #endif
  1429. ///////////////////////////////////////////////////////////////////////////////
  1430. // PResourceString
  1431. #if defined(_PRESOURCESTRING)
  1432. PResourceString::PResourceString(PRESOURCE_ID resID)
  1433. {
  1434.   Construct(resID);
  1435. }
  1436. PResourceString::PResourceString(PRESOURCE_ID resID, const PString & dflt)
  1437. {
  1438.   Construct(resID);
  1439.   if (IsEmpty())
  1440.     strcpy(GetPointer(dflt.GetLength()+1), dflt);
  1441. }
  1442. #endif
  1443. ///////////////////////////////////////////////////////////////////////////////
  1444. // PApplication
  1445. #if defined(_PAPPLICATION)
  1446. PApplication & PApplication::Current()
  1447. {
  1448.   PApplication & app = (PApplication &)PProcess::Current();
  1449.   PAssert(app.IsDescendant(PApplication::Class()), "Invalid PApplication class");
  1450.   return app;
  1451. }
  1452. void PApplication::Construct()
  1453. {
  1454.   balloonee = NULL;
  1455.   balloon = NULL;
  1456.   blowUpTimer.SetNotifier(PCREATE_NOTIFIER(BlowUpBalloon));
  1457.   aboutMenuItemString = PResourceString(PSTD_ID_STR_ABOUT_MENU, "&About...");
  1458.   aboutDialogID = 0;
  1459. }
  1460. void PApplication::PassMainLoop()
  1461. {
  1462. }
  1463. void PApplication::OnAbout()
  1464. {
  1465.   if (aboutDialogID != 0) {
  1466.     PAboutDialog dlg(mainWindow, aboutDialogID);
  1467.     dlg.RunModal();
  1468.   }
  1469.   else {
  1470.     PResourceString title(PSTD_ID_STR_ABOUT_TEXT,
  1471.                                        "Portable Windows Library Application");
  1472.     PStringStream s;
  1473.     s << title << 'n' << GetName();
  1474.     if (!GetVersion(TRUE).IsEmpty())
  1475.       s << " v" << GetVersion(TRUE);
  1476.     if (!GetManufacturer().IsEmpty())
  1477.       s << " by " << GetManufacturer();
  1478. #if PMEMORY_CHECK
  1479.     PMemoryHeap::DumpStatistics(s);
  1480. #endif
  1481.     PSimpleDialog::Info(mainWindow, s);
  1482.   }
  1483. }
  1484. PBalloon * PApplication::DoBalloonHelp(PInteractor * interactor, int action)
  1485. {
  1486.   switch (action) {
  1487.     case 0 :
  1488.       if (balloon == NULL)
  1489.         if (interactor != NULL)
  1490.           blowUpTimer = blowUpTimeout;
  1491.         else
  1492.           blowUpTimer = 0;
  1493.       else if (balloon != interactor && balloon->GetParent() != interactor) {
  1494.         PBalloon * oldBalloon = balloon;
  1495.         PBalloon * newBalloon = balloon;
  1496.         if (interactor != NULL)
  1497.           newBalloon = interactor->OnBalloonHelp();
  1498.         if (oldBalloon == newBalloon)
  1499.           blowUpTimer = 0;
  1500.         else {
  1501.           delete oldBalloon;
  1502.           balloon = newBalloon;
  1503.         }
  1504.       }
  1505.       balloonee = interactor;
  1506.       break;
  1507.     case 1 :
  1508.       balloon = (PBalloon *)interactor;
  1509.   }
  1510.   return balloon;
  1511. }
  1512. void PApplication::BlowUpBalloon(PTimer &, INT)
  1513. {
  1514.   if (balloonee != NULL)
  1515.     balloon = balloonee->OnBalloonHelp();
  1516. }
  1517. void PApplication::DelayedCloseInteractor(PInteractor * interactor)
  1518. {
  1519.   if (delayedCloseInteractors.GetObjectsIndex(interactor) == P_MAX_INDEX)
  1520.     delayedCloseInteractors.Append(interactor);
  1521. }
  1522. #endif
  1523. ///////////////////////////////////////////////////////////////////////////////
  1524. // PCommandSink
  1525. PCommandSink::PCommandSink(const char * className, const char * commandName)
  1526. {
  1527.   PApplication::Current().commandManager.Register(className, commandName, this);
  1528. }
  1529. BOOL PCommandSink::Enabled(PTitledWindow *) const
  1530. {
  1531.   return TRUE;
  1532. }
  1533. PINDEX PCommandSink::Value(PTitledWindow *) const
  1534. {
  1535.   return 0;
  1536. }
  1537. ///////////////////////////////////////////////////////////////////////////////
  1538. // PCommandSource
  1539. void PCommandSource::Call(PObject & notifier, INT extra) const
  1540. {
  1541.   PCommandSink * sink = NULL;
  1542.   PTitledWindow * wind = (PTitledWindow *)object;
  1543.   if (wind->IsDescendant(PMDIFrameWindow::Class())) {
  1544.     PMDIDocWindow * child = ((PMDIFrameWindow *)wind)->GetActiveDocument();
  1545.     if (child != NULL) {
  1546.       unsigned ancestor = 0;
  1547.       for (;;) {
  1548.         const char * className = child->GetClass(ancestor);
  1549.         if (strcmp(className, PMDIDocWindow::Class()) == 0)
  1550.           break;
  1551.         sink = PApplication::Current().commandManager.Find(className, name);
  1552.         if (sink != NULL) {
  1553.           wind = child;
  1554.           break;
  1555.         }
  1556.         ancestor++;
  1557.       }
  1558.     }
  1559.   }
  1560.   if (sink == NULL)
  1561.     sink = PApplication::Current().commandManager.Find(wind->GetClass(),name);
  1562.   if (notifier.IsDescendant(PMenuItem::Class())) {
  1563.     if (extra) {
  1564.       PMenuItem & item = (PMenuItem &)notifier;
  1565.       item.Enable(sink != NULL && sink->Enabled(wind));
  1566.       item.SetGroupCheck(sink != NULL ? sink->Value(wind) : 0);
  1567.     }
  1568.     else if (sink != NULL)
  1569.       sink->Execute(wind);
  1570.   }
  1571.   else {
  1572.     PControl & item = (PControl &)notifier;
  1573.     switch (extra) {
  1574.       case PControl::NotifyUpdate :
  1575.         if (sink != NULL)
  1576.           sink->Value(wind);
  1577.         break;
  1578.       case PControl::NotifyEnable :
  1579.         item.Enable(sink != NULL && sink->Enabled(wind));
  1580.         break;
  1581.       case PControl::NotifyChange :
  1582.         if (sink != NULL)
  1583.           sink->Execute(wind);
  1584.     }
  1585.   }
  1586. }
  1587. ///////////////////////////////////////////////////////////////////////////////
  1588. // PCommandManager
  1589. void PCommandManager::Register(const char * className,
  1590.                                  const char * commandName, PCommandSink * sink)
  1591. {
  1592.   PString classNameString = className;
  1593.   if (commands.GetAt(classNameString) == NULL)
  1594.     commands.SetAt(classNameString, new CommandsByName);
  1595.   commands[classNameString].SetAt(PString(commandName), sink);
  1596. }
  1597. PCommandSink * PCommandManager::Find(const PString & className,
  1598.                                                   const PString & commandName)
  1599. {
  1600.   if (commands.GetAt(className) == NULL)
  1601.     return NULL;
  1602.   return (PCommandSink *)commands[className].GetAt(commandName);
  1603. }
  1604. #undef new
  1605. // End Of File ///////////////////////////////////////////////////////////////