~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/widget/src/mac/nsNativeScrollbar.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Mozilla Public License
 
6
 * Version 1.1 (the "License"); you may not use this file except in
 
7
 * compliance with the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/MPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is mozilla.org code.
 
16
 *
 
17
 * The Initial Developer of the Original Code is 
 
18
 * Netscape Communications Corporation.
 
19
 * Portions created by the Initial Developer are Copyright (C) 2002
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *
 
24
 * Alternatively, the contents of this file may be used under the terms of
 
25
 * either the GNU General Public License Version 2 or later (the "GPL"), or 
 
26
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
27
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
28
 * of those above. If you wish to allow use of your version of this file only
 
29
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
30
 * use your version of this file under the terms of the MPL, indicate your
 
31
 * decision by deleting the provisions above and replace them with the notice
 
32
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
33
 * the provisions above, a recipient may use your version of this file under
 
34
 * the terms of any one of the NPL, the GPL or the LGPL.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
38
 
 
39
#include "nsNativeScrollbar.h"
 
40
#include "nsIDeviceContext.h"
 
41
#if TARGET_CARBON || (UNIVERSAL_INTERFACES_VERSION >= 0x0330)
 
42
#include <ControlDefinitions.h>
 
43
#endif
 
44
 
 
45
#include "nsWidgetAtoms.h"
 
46
#include "nsWatchTask.h"
 
47
#include "nsINameSpaceManager.h"
 
48
#include "nsIDOMElement.h"
 
49
#include "nsIScrollbarMediator.h"
 
50
 
 
51
#include "Sound.h"
 
52
 
 
53
inline void BoundsCheck(PRInt32 low, PRUint32& value, PRUint32 high)
 
54
{
 
55
  if ((PRInt32) value < low)
 
56
    value = low;
 
57
  if (value > high)
 
58
    value = high;
 
59
}
 
60
 
 
61
//
 
62
// StControlActionProcOwner
 
63
//
 
64
// A class that wraps a control action proc so that it is disposed of
 
65
// correctly when the shared library shuts down
 
66
//
 
67
class StNativeControlActionProcOwner {
 
68
public:
 
69
  
 
70
  StNativeControlActionProcOwner ( )
 
71
  {
 
72
    sControlActionProc = NewControlActionUPP(nsNativeScrollbar::ScrollActionProc);
 
73
    NS_ASSERTION(sControlActionProc, "Couldn't create live scrolling action proc");
 
74
  }
 
75
  ~StNativeControlActionProcOwner ( )
 
76
  {
 
77
    if ( sControlActionProc )
 
78
      DisposeControlActionUPP(sControlActionProc);
 
79
  }
 
80
 
 
81
  ControlActionUPP ActionProc() { return sControlActionProc; }
 
82
  
 
83
private:
 
84
  ControlActionUPP sControlActionProc;  
 
85
};
 
86
 
 
87
 
 
88
static ControlActionUPP ScrollbarActionProc ( );
 
89
 
 
90
static ControlActionUPP 
 
91
ScrollbarActionProc ( )
 
92
{
 
93
  static StNativeControlActionProcOwner sActionProcOwner;
 
94
  return sActionProcOwner.ActionProc();
 
95
}
 
96
 
 
97
 
 
98
NS_IMPL_ISUPPORTS_INHERITED1(nsNativeScrollbar, nsWindow, nsINativeScrollbar)
 
99
 
 
100
nsNativeScrollbar::nsNativeScrollbar()
 
101
  : nsMacControl()
 
102
  , mContent(nsnull)
 
103
  , mMediator(nsnull)
 
104
  , mLineIncrement(0)
 
105
  , mMaxValue(0)
 
106
  , mVisibleImageSize(0)
 
107
  , mMouseDownInScroll(PR_FALSE)
 
108
  , mClickedPartCode(0)
 
109
{
 
110
  WIDGET_SET_CLASSNAME("nsNativeScrollbar");
 
111
  SetControlType(kControlScrollBarLiveProc);
 
112
}
 
113
 
 
114
 
 
115
nsNativeScrollbar::~nsNativeScrollbar()
 
116
{
 
117
}
 
118
 
 
119
 
 
120
 
 
121
//
 
122
// ScrollActionProc
 
123
//
 
124
// Called from the OS toolbox while the scrollbar is being tracked.
 
125
//
 
126
pascal void
 
127
nsNativeScrollbar::ScrollActionProc(ControlHandle ctrl, ControlPartCode part)
 
128
{
 
129
  nsNativeScrollbar* self = (nsNativeScrollbar*)(::GetControlReference(ctrl));
 
130
  NS_ASSERTION(self, "NULL nsNativeScrollbar");
 
131
  if ( self )
 
132
    self->DoScrollAction(part);
 
133
}
 
134
 
 
135
 
 
136
//
 
137
// DoScrollAction
 
138
//
 
139
// Called from the action proc of the scrollbar, adjust the control's
 
140
// value as well as the value in the content node which communicates
 
141
// to gecko that the document is scrolling.
 
142
// 
 
143
void
 
144
nsNativeScrollbar::DoScrollAction(ControlPartCode part)
 
145
{
 
146
  PRUint32 oldPos, newPos;
 
147
  PRUint32 incr;
 
148
  PRUint32 visibleImageSize;
 
149
  PRInt32 scrollBarMessage = 0;
 
150
  GetPosition(&oldPos);
 
151
  GetLineIncrement(&incr);
 
152
  GetViewSize(&visibleImageSize);
 
153
  switch(part)
 
154
  {
 
155
    //
 
156
    // For the up/down buttons, scroll up or down by the line height and 
 
157
    // update the attributes on the content node (the scroll frame listens
 
158
    // for these attributes and will scroll accordingly). However,
 
159
    // if we have a mediator, we're in an outliner and we have to scroll by
 
160
    // lines. Outliner ignores the params to ScrollbarButtonPressed() except
 
161
    // to check if one is greater than the other to indicate direction.
 
162
    //
 
163
    
 
164
    case kControlUpButtonPart:
 
165
      newPos = oldPos - (mLineIncrement ? mLineIncrement : 1);
 
166
      if ( mMediator ) {
 
167
        BoundsCheck(0, newPos, mMaxValue);
 
168
        mMediator->ScrollbarButtonPressed(oldPos, newPos);
 
169
      } else {
 
170
        UpdateContentPosition(newPos);
 
171
      }
 
172
      break;
 
173
         
 
174
    case kControlDownButtonPart:
 
175
      newPos = oldPos + (mLineIncrement ? mLineIncrement : 1);
 
176
      if ( mMediator ) {
 
177
        BoundsCheck(0, newPos, mMaxValue);
 
178
        mMediator->ScrollbarButtonPressed(oldPos, newPos);
 
179
      } else {
 
180
        UpdateContentPosition(newPos); 
 
181
      }
 
182
      break;
 
183
    
 
184
    //
 
185
    // For page up/down and dragging the thumb, scroll by the page height
 
186
    // (or directly report the value of the scrollbar) and update the attributes
 
187
    // on the content node (as above). If we have a mediator, we're in an
 
188
    // outliner so tell it directly that the position has changed. Note that
 
189
    // outliner takes signed values, so we have to convert our unsigned to 
 
190
    // signed values first.
 
191
    //
 
192
    
 
193
    case kControlPageUpPart:
 
194
      newPos = oldPos - visibleImageSize;
 
195
      UpdateContentPosition(newPos);
 
196
      if ( mMediator ) {
 
197
        PRInt32 op = oldPos, np = mValue;
 
198
        if ( np < 0 )
 
199
          np = 0;
 
200
        mMediator->PositionChanged(op, np);
 
201
      }
 
202
      break;
 
203
      
 
204
    case kControlPageDownPart:
 
205
      newPos = oldPos + visibleImageSize;
 
206
      UpdateContentPosition(newPos);
 
207
      if ( mMediator ) {
 
208
        PRInt32 op = oldPos, np = mValue;
 
209
        if ( np < 0 )
 
210
          np = 0;
 
211
        mMediator->PositionChanged(op, np);
 
212
      }
 
213
      break;
 
214
      
 
215
    case kControlIndicatorPart:
 
216
      newPos = ::GetControl32BitValue(GetControl());
 
217
      UpdateContentPosition(newPos);
 
218
      if ( mMediator ) {
 
219
        PRInt32 op = oldPos, np = mValue;
 
220
        if ( np < 0 )
 
221
          np = 0;
 
222
        mMediator->PositionChanged(op, np);
 
223
      }
 
224
      break;
 
225
  }
 
226
  EndDraw();
 
227
    
 
228
        // update the area of the parent uncovered by the scrolling. Since
 
229
        // we may be in a tight loop, we need to manually validate the area
 
230
        // we just updated so the update rect doesn't continue to get bigger
 
231
        // and bigger the more we scroll.
 
232
        nsCOMPtr<nsIWidget> parent ( dont_AddRef(GetParent()) );
 
233
        parent->Update();
 
234
        parent->Validate();
 
235
 
 
236
  StartDraw();
 
237
}
 
238
 
 
239
 
 
240
//
 
241
// UpdateContentPosition
 
242
//
 
243
// Tell the content node that the scrollbar has changed value and
 
244
// then update the scrollbar's position
 
245
//
 
246
void
 
247
nsNativeScrollbar::UpdateContentPosition(PRUint32 inNewPos)
 
248
{
 
249
  if ( inNewPos == mValue || !mContent )   // break any possible recursion
 
250
    return;
 
251
 
 
252
  // guarantee |inNewPos| is in the range of [0, mMaxValue] so it's correctly unsigned
 
253
  BoundsCheck(0, inNewPos, mMaxValue);
 
254
 
 
255
  // convert the int to a string
 
256
  nsAutoString buffer;
 
257
  buffer.AppendInt(inNewPos);
 
258
  
 
259
  mContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::curpos, buffer, PR_TRUE);
 
260
  SetPosition(inNewPos);
 
261
}
 
262
 
 
263
 
 
264
/**-------------------------------------------------------------------------------
 
265
 * DispatchMouseEvent handle an event for this scrollbar
 
266
 * @update  dc 08/31/98
 
267
 * @Param aEvent -- The mouse event to respond to for this button
 
268
 * @return -- True if the event was handled, PR_FALSE if we did not handle it.
 
269
 */ 
 
270
PRBool
 
271
nsNativeScrollbar::DispatchMouseEvent(nsMouseEvent &aEvent)
 
272
{
 
273
  PRBool eatEvent = PR_FALSE;
 
274
  switch (aEvent.message)
 
275
  {
 
276
    case NS_MOUSE_LEFT_DOUBLECLICK:
 
277
    case NS_MOUSE_LEFT_BUTTON_DOWN:
 
278
      NS_ASSERTION(this != 0, "NULL nsNativeScrollbar2");
 
279
      ::SetControlReference(mControl, (UInt32) this);
 
280
      StartDraw();
 
281
      {
 
282
        Point thePoint;
 
283
        thePoint.h = aEvent.point.x;
 
284
        thePoint.v = aEvent.point.y;
 
285
        mClickedPartCode = ::TestControl(mControl, thePoint);
 
286
        if (mClickedPartCode > 0)
 
287
          ::HiliteControl(mControl, mClickedPartCode);
 
288
 
 
289
        switch (mClickedPartCode)
 
290
        {
 
291
          case kControlUpButtonPart:
 
292
          case kControlDownButtonPart:
 
293
          case kControlPageUpPart:
 
294
          case kControlPageDownPart:
 
295
          case kControlIndicatorPart:
 
296
            // We are assuming Appearance 1.1 or later, so we
 
297
            // have the "live scroll" variant of the scrollbar,
 
298
            // which lets you pass the action proc to TrackControl
 
299
            // for the thumb (this was illegal in previous
 
300
            // versions of the defproc).
 
301
            nsWatchTask::GetTask().Suspend();
 
302
            ::TrackControl(mControl, thePoint, ScrollbarActionProc());
 
303
            nsWatchTask::GetTask().Resume();
 
304
            ::HiliteControl(mControl, 0);
 
305
            // We don't dispatch the mouseDown event because mouseUp is eaten
 
306
            // by TrackControl anyway and the only messages the app really
 
307
            // cares about are the NS_SCROLLBAR_xxx messages.
 
308
            eatEvent = PR_TRUE;
 
309
            break;
 
310
        }
 
311
        SetPosition(mValue);
 
312
      }
 
313
      EndDraw();
 
314
      break;
 
315
 
 
316
 
 
317
    case NS_MOUSE_LEFT_BUTTON_UP:
 
318
      mClickedPartCode = 0;
 
319
      break;
 
320
 
 
321
    case NS_MOUSE_EXIT:
 
322
      if (mWidgetArmed)
 
323
      {
 
324
        StartDraw();
 
325
        ::HiliteControl(mControl, 0);
 
326
        EndDraw();
 
327
      }
 
328
      break;
 
329
 
 
330
    case NS_MOUSE_ENTER:
 
331
      if (mWidgetArmed)
 
332
      {
 
333
        StartDraw();
 
334
        ::HiliteControl(mControl, mClickedPartCode);
 
335
        EndDraw();
 
336
      }
 
337
      break;
 
338
  }
 
339
 
 
340
  if (eatEvent)
 
341
    return PR_TRUE;
 
342
  return (Inherited::DispatchMouseEvent(aEvent));
 
343
 
 
344
}
 
345
 
 
346
 
 
347
//
 
348
// SetMaxRange
 
349
//
 
350
// Set the maximum range of a scroll bar. This should be set to the
 
351
// full scrollable area minus the visible area.
 
352
//
 
353
NS_IMETHODIMP
 
354
nsNativeScrollbar::SetMaxRange(PRUint32 aEndRange)
 
355
{
 
356
  mMaxValue = ((int)aEndRange) > 0 ? aEndRange : 10;
 
357
  if ( GetControl() ) {
 
358
    StartDraw();
 
359
    ::SetControl32BitMaximum(GetControl(), mMaxValue);
 
360
    EndDraw();
 
361
  }
 
362
  return NS_OK;
 
363
}
 
364
 
 
365
 
 
366
//
 
367
// GetMaxRange
 
368
//
 
369
// Get the maximum range of a scroll bar
 
370
//
 
371
NS_IMETHODIMP
 
372
nsNativeScrollbar::GetMaxRange(PRUint32* aMaxRange)
 
373
{
 
374
  *aMaxRange = mMaxValue;
 
375
  return NS_OK;
 
376
}
 
377
 
 
378
 
 
379
//
 
380
// SetPosition
 
381
//
 
382
// Set the current position of the slider and redraw
 
383
//
 
384
NS_IMETHODIMP
 
385
nsNativeScrollbar::SetPosition(PRUint32 aPos)
 
386
{
 
387
  if ((PRInt32)aPos < 0)
 
388
    aPos = 0;
 
389
 
 
390
  PRInt32 oldValue = mValue;
 
391
  
 
392
  // while we _should_ be ensuring that we don't set our value higher
 
393
  // than our max value, the gfx scrollview code plays fast and loose
 
394
  // with the rules while going back/forward and adjusts the value to the
 
395
  // previous value long before it sets the max. As a result, we would
 
396
  // lose the given value (since max would most likely be 0). The only
 
397
  // way around that is to relax our restrictions a little bit. (bug 135191)
 
398
  //   mValue = ((PRInt32)aPos) > mMaxValue ? mMaxValue : ((int)aPos);
 
399
  mValue = aPos;
 
400
  
 
401
  // redraw the scrollbar. It needs to be synchronous otherwise we end
 
402
  // up drawing at 0,0, probably because of the associated view.
 
403
  if ( mValue != oldValue )
 
404
    Invalidate(PR_TRUE);
 
405
  
 
406
  return NS_OK;
 
407
}
 
408
 
 
409
 
 
410
//
 
411
// GetPosition
 
412
//
 
413
// Get the current position of the slider
 
414
//
 
415
NS_IMETHODIMP
 
416
nsNativeScrollbar::GetPosition(PRUint32* aPos)
 
417
{
 
418
  *aPos = mValue;
 
419
  return NS_OK;
 
420
}
 
421
 
 
422
 
 
423
//
 
424
// SetViewSize
 
425
//
 
426
// According to the toolbox docs, we pass the height of the
 
427
// visible view area to SetControlViewSize(). Assuming we've set
 
428
// the max to the total area - view height, this will give us a correct
 
429
// proportional scrollbar.
 
430
//
 
431
NS_IMETHODIMP
 
432
nsNativeScrollbar::SetViewSize(PRUint32 aSize)
 
433
{
 
434
  mVisibleImageSize = ((int)aSize) > 0 ? aSize : 1;
 
435
  
 
436
  if ( GetControl() )  {
 
437
    StartDraw();
 
438
    SetControlViewSize(GetControl(), mVisibleImageSize);
 
439
    EndDraw();
 
440
  }
 
441
  return NS_OK;
 
442
}
 
443
 
 
444
 
 
445
//
 
446
// GetViewSize
 
447
//
 
448
// Get the height of the visible view area.
 
449
//
 
450
NS_IMETHODIMP
 
451
nsNativeScrollbar::GetViewSize(PRUint32* aSize)
 
452
{
 
453
  *aSize = mVisibleImageSize;
 
454
  return NS_OK;
 
455
}
 
456
 
 
457
 
 
458
//
 
459
// SetLineIncrement
 
460
//
 
461
// Set the line increment of the scroll bar
 
462
//
 
463
NS_IMETHODIMP
 
464
nsNativeScrollbar::SetLineIncrement(PRUint32 aLineIncrement)
 
465
{
 
466
  mLineIncrement  = (((int)aLineIncrement) > 0 ? aLineIncrement : 1);
 
467
  return NS_OK;
 
468
}
 
469
 
 
470
 
 
471
//
 
472
// GetLineIncrement
 
473
//
 
474
// Get the line increment of the scroll bar
 
475
//
 
476
NS_IMETHODIMP
 
477
nsNativeScrollbar::GetLineIncrement(PRUint32* aLineIncrement)
 
478
{
 
479
  *aLineIncrement = mLineIncrement;
 
480
  return NS_OK;
 
481
}
 
482
 
 
483
 
 
484
//
 
485
// GetNarrowSize
 
486
//
 
487
// Ask the appearance manager for the dimensions of the narrow axis
 
488
// of the scrollbar. We cheat and assume the width of a vertical scrollbar
 
489
// is the same as the height of a horizontal scrollbar. *shrug*. Shoot me.
 
490
//
 
491
NS_IMETHODIMP
 
492
nsNativeScrollbar::GetNarrowSize(PRInt32* outSize)
 
493
{
 
494
  if ( *outSize )
 
495
    return NS_ERROR_FAILURE;
 
496
  SInt32 width = 0;
 
497
#if TARGET_CARBON
 
498
  ::GetThemeMetric(kThemeMetricScrollBarWidth, &width);
 
499
#else
 
500
  width = 16;
 
501
#endif
 
502
  *outSize = width;
 
503
  return NS_OK;
 
504
}
 
505
 
 
506
 
 
507
//
 
508
// SetContent
 
509
//
 
510
// Hook up this native scrollbar to the rest of gecko. We care about
 
511
// the content so we can set attributes on it to affect the scrollview. We
 
512
// care about the mediator for <outliner> so we can do row-based scrolling.
 
513
//
 
514
NS_IMETHODIMP
 
515
nsNativeScrollbar::SetContent(nsIContent* inContent, nsIScrollbarMediator* inMediator)
 
516
{
 
517
  mContent = inContent;
 
518
  mMediator = inMediator;
 
519
  return NS_OK;
 
520
}