home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / mac / UserInterface / CInlineEditField.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  11.1 KB  |  338 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*======================================================================================
  20.     AUTHOR:            Ted Morris <tmorris@netscape.com> - 17 DEC 96
  21.  
  22.     MODIFICATIONS:
  23.  
  24.     Date            Person            Description
  25.     ----            ------            -----------
  26. ======================================================================================*/
  27.  
  28.  
  29. /*====================================================================================*/
  30.     #pragma mark INCLUDE FILES
  31. /*====================================================================================*/
  32.  
  33. #include "CInlineEditField.h"
  34.  
  35.  
  36. /*====================================================================================*/
  37.     #pragma mark TYPEDEFS
  38. /*====================================================================================*/
  39.  
  40.  
  41. /*====================================================================================*/
  42.     #pragma mark CONSTANTS
  43. /*====================================================================================*/
  44.  
  45.  
  46. /*====================================================================================*/
  47.     #pragma mark INTERNAL CLASS DECLARATIONS
  48. /*====================================================================================*/
  49.  
  50.  
  51. /*====================================================================================*/
  52.     #pragma mark INTERNAL FUNCTION PROTOTYPES
  53. /*====================================================================================*/
  54.  
  55.  
  56. /*====================================================================================*/
  57.     #pragma mark CLASS IMPLEMENTATIONS
  58. /*====================================================================================*/
  59.  
  60.  
  61. /*======================================================================================
  62.     Set the descriptor and adjust the frame size to the new text.
  63. ======================================================================================*/
  64.  
  65. void CInlineEditField::SetDescriptor(ConstStr255Param inDescriptor) {
  66.  
  67.     inherited::SetDescriptor(inDescriptor);
  68.     
  69.     if (mGrowableBorder)
  70.         AdjustFrameWidthToText();
  71.         
  72.     mOriginalName = inDescriptor;
  73. }
  74.  
  75.  
  76. /*======================================================================================
  77.     Update the text and edit location for this field. inEditText specifies the text to
  78.     start editing, inImageTopLeft is the top, left corner for the edit field in the
  79.     image coordinates of its superview, ioMouseDown specifies the mouse click location
  80.     if the edit field is activated by a mouse click, or nil to just select all of the
  81.     edit field text. ioMouseDown can be an exact copy of the SMouseDownEvent passed to
  82.     ClickSelf() or ClickSelect().
  83.     
  84.     Pass inEditText == nil to hide the edit field and update the port immediately.
  85. ======================================================================================*/
  86.  
  87. void CInlineEditField::UpdateEdit(ConstStr255Param inEditText, const SPoint32 *inImageTopLeft,
  88.                                   SMouseDownEvent *ioMouseDown) {
  89.  
  90.     Boolean wasVisible = IsVisible();
  91.     
  92.     if ( inEditText ) {
  93.     
  94.         Assert_(inImageTopLeft != nil);
  95.         
  96.         SetDescriptor(inEditText);
  97.         Show();
  98.         if ( wasVisible ) {
  99.             Refresh();
  100.         } else {
  101.             DontRefresh();
  102.         }
  103.         PlaceInSuperImageAt(inImageTopLeft->h, inImageTopLeft->v, false);
  104.         if ( wasVisible ) UpdatePort();
  105.         if ( !ioMouseDown ) {
  106.             FocusDraw();
  107.             //StEmptyVisRgn emptyRgn(GetMacPort());
  108.             ::TESetSelect(0, max_Int16, mTextEditH);
  109.         }
  110.         Draw(nil);
  111.         
  112.         sLastPaneClicked = nil;
  113.         (**mTextEditH).clickTime = 0;    // No double clicks in new field
  114.         
  115.         if ( ioMouseDown != nil ) {
  116.             ioMouseDown->whereLocal = ioMouseDown->wherePort;
  117.             Click(*ioMouseDown);
  118.         } else {
  119.             SwitchTarget(this);
  120.         }
  121.     } else {
  122.         if ( wasVisible ) {
  123.             Hide();
  124.             UpdatePort();
  125.         }
  126.     }
  127. }
  128.  
  129.  
  130.  
  131. /*======================================================================================
  132.     Finish creating the edit field.
  133. ======================================================================================*/
  134.  
  135. void CInlineEditField::FinishCreateSelf(void) {
  136.     
  137.     inherited::FinishCreateSelf();
  138.     
  139.     Hide();    // Should be invisible to start
  140.  
  141.     // Resize the pane so that it fits the text vertically
  142.     
  143.     Int16 height = (**mTextEditH).lineHeight;
  144.  
  145.     if ( mHasBox ) height += (cEditBoxMargin<<1);
  146.     
  147.     ResizeFrameTo(mFrameSize.width, height, false);
  148. }
  149.  
  150.  
  151. /*======================================================================================
  152.     Refresh the border as well.
  153. ======================================================================================*/
  154.  
  155. void CInlineEditField::ResizeFrameBy(Int16 inWidthDelta, Int16 inHeightDelta, Boolean inRefresh) {
  156.  
  157.     if ( !inWidthDelta && !inHeightDelta ) return;
  158.     
  159.     inherited::ResizeFrameBy(inWidthDelta, inHeightDelta, inRefresh);
  160.     
  161.     if ( inRefresh && mGrowableBorder) {
  162.         Rect portRect, refreshRect;
  163.         CalcPortFrameRect(portRect);
  164.         if ( inWidthDelta != 0 ) {
  165.             refreshRect = portRect;
  166.             if ( inWidthDelta > 0 ) {
  167.                 refreshRect.right -= inWidthDelta; 
  168.                 refreshRect.left = refreshRect.right - cRefreshMargin;
  169.             } else {
  170.                 refreshRect.left = refreshRect.right - cRefreshMargin;
  171.             }
  172.             InvalPortRect(&refreshRect);
  173.         }
  174.         if ( inHeightDelta != 0 ) {
  175.             refreshRect = portRect;
  176.             if ( inHeightDelta > 0 ) {
  177.                 refreshRect.bottom -= inWidthDelta; 
  178.                 refreshRect.top = refreshRect.bottom - cRefreshMargin;
  179.             } else {
  180.                 refreshRect.top = refreshRect.bottom - cRefreshMargin;
  181.             }
  182.             InvalPortRect(&refreshRect);
  183.         }
  184.     }
  185. }
  186.  
  187.  
  188. /*======================================================================================
  189.     Handle returns, enters, tabs.
  190. ======================================================================================*/
  191.  
  192. Boolean CInlineEditField::HandleKeyPress(const EventRecord &inKeyEvent) {
  193.  
  194.     if ( !(inKeyEvent.modifiers & cmdKey) ) {
  195.         Int16 theKey = inKeyEvent.message & charCodeMask;
  196.         
  197.         switch ( theKey ) {
  198.             
  199.             // when the user hits escape, set the name back to the original and fall
  200.             // through to broadcast the "change" and hide the pane.
  201.             case char_Escape:
  202.                     SetDescriptor(mOriginalName);
  203.                     
  204.             case char_Enter:
  205.             case char_Return: {
  206.                     PaneIDT paneID = mPaneID;
  207.                     BroadcastMessage(msg_HidingInlineEditField, &paneID);
  208.                     StopBroadcasting();            // don't broadcast, else we'll end
  209.                                                 // up sending another message when we hide the pane.
  210.                     UpdateEdit(nil, nil, nil);    // Remove editing
  211.                     StartBroadcasting();
  212.                     return true;                // keypress handled
  213.                 }
  214.                 break;
  215.         }
  216.     }
  217.     
  218.     return inherited::HandleKeyPress(inKeyEvent);
  219. }
  220.  
  221.  
  222. /*======================================================================================
  223.     We are losing target status.
  224. ======================================================================================*/
  225.  
  226. void CInlineEditField::DontBeTarget(void) {
  227.  
  228.     StValueChanger<Boolean> change(mGivingUpTarget, true);
  229.  
  230.     inherited::DontBeTarget();
  231.  
  232.     PaneIDT paneID = mPaneID;
  233.     BroadcastMessage(msg_HidingInlineEditField, &paneID);
  234.     
  235.     UpdateEdit(nil, nil, nil);    // Remove editing
  236. }
  237.  
  238.  
  239. /*======================================================================================
  240.     Set new target only if we are not giving up the target.
  241. ======================================================================================*/
  242.  
  243. void CInlineEditField::HideSelf(void) {
  244.  
  245.     if ( IsOnDuty() && !mGivingUpTarget ) {    // Shouldn't be on duty when invisible
  246.         SwitchTarget(GetSuperCommander());
  247.     }
  248. }
  249.  
  250.  
  251. /*======================================================================================
  252.     Take us off duty and turn on duty to off.
  253. ======================================================================================*/
  254.  
  255. void CInlineEditField::TakeOffDuty(void) {
  256.  
  257.     inherited::TakeOffDuty();
  258.     
  259.     mOnDuty = triState_Off;    // Taking our chain off duty means that we are hidden and
  260.                             // should no longer be in the chain of command.
  261. }
  262.  
  263.  
  264. /*======================================================================================
  265.     Adjust the frame of the edit field to the width of the text.
  266. ======================================================================================*/
  267.  
  268. void CInlineEditField::UserChangedText(void) {
  269.  
  270.     if (mGrowableBorder)
  271.     {
  272.         AdjustFrameWidthToText();
  273.     }
  274.     PaneIDT paneID = mPaneID;
  275.  
  276.     BroadcastMessage(msg_InlineEditFieldChanged, &paneID);
  277. }
  278.  
  279.  
  280. /*======================================================================================
  281.     Adjust the frame of the edit field to the bounds of the current text.
  282. ======================================================================================*/
  283.  
  284. void CInlineEditField::AdjustFrameWidthToText(void) {
  285.  
  286.     Int16 newWidth;
  287.     GetSuperView()->EstablishPort();
  288.     UTextTraits::SetPortTextTraits(mTextTraitsID);
  289.     
  290.     Str255 descriptor;
  291.     GetDescriptor(descriptor);
  292.     
  293.     newWidth = ::StringWidth(descriptor) + 2;
  294.     
  295.     if ( mHasBox ) newWidth += (cEditBoxMargin<<1);
  296.     
  297.     ResizeFrameTo(newWidth, mFrameSize.height, true);
  298.     if ( IsVisible() ) UpdatePort();    // Update immediately so there's no lag in display
  299. }
  300.  
  301. /*
  302. Why we have Growable Border mode (by kellys):
  303.  
  304. CInlineEditField is derived (indirectly) from CTSMEditField.  When we have growable
  305. borders, CInlineEditField assumes it can change the border whenever the user types.
  306. However, when the user is using a multi-byte script like Japanese, CTSMEditField
  307. "takes over" event handling.  As a result, the border doesn't resize while they're
  308. typing (Bug #81734).  
  309.  
  310. The proper thing to do is to change the event handling assumptions.  However, due to lack
  311. of time, I have made a "kludge" that avoids the problem.  Under multi-byte systems,
  312. we make the border a fixed size.  Under roman systems, we make it variable.
  313. */
  314.  
  315. /*======================================================================================
  316.     Set whether or not we use a growable frame
  317. ======================================================================================*/
  318.  
  319. void CInlineEditField::SetGrowableBorder(Boolean inGrowable) {
  320.  
  321.     if (inGrowable != mGrowableBorder) {
  322.         mGrowableBorder = inGrowable;
  323.         // ResizeFrameTo(mFrameSize.width, mFrameSize.height, true);
  324.         UserChangedText();
  325.     }
  326. }
  327.  
  328.  
  329. /*======================================================================================
  330.     Get whether or not we use a growable frame
  331. ======================================================================================*/
  332.  
  333. Boolean CInlineEditField::GetGrowableBorder() {
  334.  
  335.     return mGrowableBorder;
  336.  
  337. }
  338.