1 { $Id: $}
2 { --------------------------------------------
3 cocoaprivate.pp - Cocoa internal classes
4 --------------------------------------------
5
6 This unit contains the private classhierarchy for the Cocoa implemetations
7
8 *****************************************************************************
9 This file is part of the Lazarus Component Library (LCL)
10
11 See the file COPYING.modifiedLGPL.txt, included in this distribution,
12 for details about the license.
13 *****************************************************************************
14 }
15 unit CocoaPrivate;
16
17 {$mode objfpc}{$H+}
18 {$modeswitch objectivec1}
19 {$modeswitch objectivec2}
20 {$interfaces corba}
21 {$include cocoadefines.inc}
22
23 {.$DEFINE COCOA_DEBUG_SETBOUNDS}
24 {.$DEFINE COCOA_SPIN_DEBUG}
25 {.$DEFINE COCOA_SPINEDIT_INSIDE_CONTAINER}
26 {.$DEFINE COCOA_SUPERVIEW_HEIGHT}
27
28 interface
29
30 uses
31 // rtl+ftl
32 Types, Classes, SysUtils,
33 CGGeometry,
34 // Libs
35 MacOSAll, CocoaAll, CocoaUtils, CocoaGDIObjects,
36 cocoa_extra,
37 // LCL
38 LCLType;
39
40 const
41 SPINEDIT_DEFAULT_STEPPER_WIDTH = 15;
42 SPINEDIT_EDIT_SPACING_FOR_SELECTION = 4;
43 STATUSBAR_DEFAULT_HEIGHT = 18;
44
45 type
46 // Some components might be using CocoaPrivate for use of LCLObjCBoolean
47 // Thus this declaration needs to be here.
48 LCLObjCBoolean = cocoa_extra.LCLObjCBoolean;
49
50 { ICommonCallback }
51
52 ICommonCallback = interface
53 // mouse events
MouseUpDownEventnull54 function MouseUpDownEvent(Event: NSEvent; AForceAsMouseUp: Boolean = False; AOverrideBlock: Boolean = False): Boolean;
55 procedure MouseClick;
MouseMovenull56 function MouseMove(Event: NSEvent): Boolean;
57
58 // KeyEvXXX methods were introduced to allow a better control
59 // over when Cocoa keys processing is being called.
60 // (The initial KeyEvent() replicates Carbon implementation, and it's not
61 // suitable for Cocoa, due to the use of OOP and the extual "inherited Key..."needs to be called
62 // where for Carbon there's a special fucntion to call the "next event handler" present)
63 //
64 // The desired use is as following:
65 // Call KeyEvPrepare and pass NSEvent object
66 // after that call KeyEvBefore and pass a flag if AllowCocoaHandle
67 //
68 // The call would populate the flag. If it's "True" you should call "inherited" method (to let Cocoa handle the key).
69 // If the flag returned "False", you should not call inherited.
70 //
71 // No matter what the flag value was you should call KeyEvAfter.
72 procedure KeyEvBefore(Event: NSEvent; out AllowCocoaHandle: boolean);
73 procedure KeyEvAfter;
74 procedure KeyEvAfterDown(out AllowCocoaHandle: boolean);
75 procedure KeyEvHandled;
76 procedure SetTabSuppress(ASuppress: Boolean);
77
78 function scrollWheel(Event: NSEvent): Boolean;
79 function CanFocus: Boolean;
80 // size, pos events
81 procedure frameDidChange(sender: id);
82 procedure boundsDidChange(sender: id);
83 // misc events
84 procedure Draw(ctx: NSGraphicsContext; const bounds, dirty: NSRect);
85 procedure DrawBackground(ctx: NSGraphicsContext; const bounds, dirty: NSRect);
86 procedure DrawOverlay(ctx: NSGraphicsContext; const bounds, dirty: NSRect);
87 function ResetCursorRects: Boolean;
88 procedure BecomeFirstResponder;
89 procedure ResignFirstResponder;
90 procedure DidBecomeKeyNotification;
91 procedure DidResignKeyNotification;
92 procedure SendOnChange;
93 procedure SendOnTextChanged;
94 procedure scroll(isVert: Boolean; Pos: Integer; AScrollPart: NSScrollerPart = NSScrollerNoPart);
95 // non event methods
96 function DeliverMessage(Msg: Cardinal; WParam: WParam; LParam: LParam): LResult;
97 function GetPropStorage: TStringList;
98 function GetContext: TCocoaContext;
99 function GetTarget: TObject;
100 function GetHasCaret: Boolean;
101 function GetCallbackObject: TObject;
102 procedure SetHasCaret(AValue: Boolean);
103 function GetIsOpaque: Boolean;
104 procedure SetIsOpaque(AValue: Boolean);
105 function GetShouldBeEnabled: Boolean;
106 // the method is called, when handle is being destroyed.
107 // the callback object to stay alive a little longer than LCL object (Target)
108 // thus it needs to know that LCL object has been destroyed.
109 // After this called has been removed, any Cocoa events should not be
110 // forwarded to LCL target
111 procedure RemoveTarget;
112
113 procedure InputClientInsertText(const utf8: string);
114
115 // properties
116 property HasCaret: Boolean read GetHasCaret write SetHasCaret;
117 property IsOpaque: Boolean read GetIsOpaque write SetIsOpaque;
118 end;
119
120 { LCLObjectExtension }
121
122 LCLObjectExtension = objccategory(NSObject)
123 function lclIsEnabled: Boolean; message 'lclIsEnabled';
124 procedure lclSetEnabled(AEnabled: Boolean); message 'lclSetEnabled:';
125 function lclIsVisible: Boolean; message 'lclIsVisible';
126 procedure lclSetVisible(AVisible: Boolean); message 'lclSetVisible:';
127 function lclWindowState: Integer; message 'lclWindowState';
128
129 procedure lclInvalidateRect(const r: TRect); message 'lclInvalidateRect:';
130 procedure lclInvalidate; message 'lclInvalidate';
131 procedure lclUpdate; message 'lclUpdate';
132
133 // Returns the position of the view or window, in the immediate
134 // parent (view or screen), relative to its client coordinates system
135 // Left and Top are always returned in LCL coordinate system.
136 procedure lclRelativePos(var Left, Top: Integer); message 'lclRelativePos::';
137 procedure lclLocalToScreen(var X, Y: Integer); message 'lclLocalToScreen::';
138 procedure lclScreenToLocal(var X, Y: Integer); message 'lclScreenToLocal::';
139 function lclParent: id; message 'lclParent';
140 function lclFrame: TRect; message 'lclFrame';
141 procedure lclSetFrame(const r: TRect); message 'lclSetFrame:';
142
143 // returns rectangle describing deltas to get "Layout" rectangle from "Frame" rectangle
144 // left, top - return offsets from top-left corner of the control (not reversed as in Cocoa coordinates)
145 // (values are typically positive)
146 // right, bottom - offsets for bottom-right corner
147 // (typically negative)
148 function lclGetFrameToLayoutDelta: TRect; message 'lclGetFrameToLayoutDelta';
149
150 function lclClientFrame: TRect; message 'lclClientFrame';
151 function lclGetCallback: ICommonCallback; message 'lclGetCallback';
152 procedure lclClearCallback; message 'lclClearCallback';
153 function lclGetPropStorage: TStringList; message 'lclGetPropStorage';
154 function lclGetTarget: TObject; message 'lclGetTarget';
155 function lclDeliverMessage(Msg: Cardinal; WParam: WParam; LParam: LParam): LResult; message 'lclDeliverMessage:::';
156 function lclContentView: NSView; message 'lclContentView';
157 procedure lclOffsetMousePos(var Point: NSPoint); message 'lclOffsetMousePos:';
158 procedure lclExpectedKeys(var wantTabs, wantArrows, wantReturn, wantAll: Boolean); message 'lclExpectedKeys::::';
159 function lclIsMouseInAuxArea(Event: NSEvent): Boolean; message 'lclMouseInAuxArea:';
160 end;
161
162 { LCLViewExtension }
163
164 LCLViewExtension = objccategory(NSView)
165 function lclInitWithCreateParams(const AParams: TCreateParams): id; message 'lclInitWithCreateParams:';
166 function lclIsEnabled: Boolean; message 'lclIsEnabled'; reintroduce;
167 procedure lclSetEnabled(AEnabled: Boolean); message 'lclSetEnabled:'; reintroduce;
168
169 function lclIsVisible: Boolean; message 'lclIsVisible'; reintroduce;
170 procedure lclSetVisible(AVisible: Boolean); message 'lclSetVisible:'; reintroduce;
171 function lclIsPainting: Boolean; message 'lclIsPainting';
172 procedure lclInvalidateRect(const r: TRect); message 'lclInvalidateRect:'; reintroduce;
173 procedure lclInvalidate; message 'lclInvalidate'; reintroduce;
174 procedure lclUpdate; message 'lclUpdate'; reintroduce;
175 procedure lclRelativePos(var Left, Top: Integer); message 'lclRelativePos::'; reintroduce;
176 procedure lclLocalToScreen(var X, Y: Integer); message 'lclLocalToScreen::'; reintroduce;
177 procedure lclScreenToLocal(var X, Y: Integer); message 'lclScreenToLocal::'; reintroduce;
178 function lclParent: id; message 'lclParent'; reintroduce;
179 function lclFrame: TRect; message 'lclFrame'; reintroduce;
180 procedure lclSetFrame(const r: TRect); message 'lclSetFrame:'; reintroduce;
181 function lclClientFrame: TRect; message 'lclClientFrame'; reintroduce;
182 function lclContentView: NSView; message 'lclContentView'; reintroduce;
183 procedure lclOffsetMousePos(var Point: NSPoint); message 'lclOffsetMousePos:'; reintroduce;
184 end;
185
186 { LCLControlExtension }
187
188 LCLControlExtension = objccategory(NSControl)
189 function lclIsEnabled: Boolean; message 'lclIsEnabled'; reintroduce;
190 procedure lclSetEnabled(AEnabled: Boolean); message 'lclSetEnabled:'; reintroduce;
191 end;
192
193 { TCocoaCustomControl }
194
195 TCocoaCustomControl = objcclass(NSControl, NSTextInputClientProtocol)
196 private
197 fstr : NSString;
198
199 isdrawing : integer;
200 faileddraw : Boolean;
201 public
202 callback: ICommonCallback;
203 auxMouseByParent: Boolean;
204 procedure dealloc; override;
205 function acceptsFirstResponder: LCLObjCBoolean; override;
206 procedure drawRect(dirtyRect: NSRect); override;
207 function lclGetCallback: ICommonCallback; override;
208 procedure lclClearCallback; override;
209 function lclIsMouseInAuxArea(Event: NSevent): Boolean; override;
210 // mouse
211 function acceptsFirstMouse(event: NSEvent): LCLObjCBoolean; override;
212 procedure mouseDown(event: NSEvent); override;
213 procedure mouseUp(event: NSEvent); override;
214 procedure rightMouseDown(event: NSEvent); override;
215 procedure rightMouseUp(event: NSEvent); override;
216 procedure rightMouseDragged(event: NSEvent); override;
217 procedure otherMouseDown(event: NSEvent); override;
218 procedure otherMouseUp(event: NSEvent); override;
219 procedure otherMouseDragged(event: NSEvent); override;
220 procedure mouseDragged(event: NSEvent); override;
221 procedure mouseEntered(event: NSEvent); override;
222 procedure mouseExited(event: NSEvent); override;
223 procedure mouseMoved(event: NSEvent); override;
224 procedure scrollWheel(event: NSEvent); override;
225 // nsview
226 procedure setFrame(aframe: NSRect); override;
227 // other
228 procedure resetCursorRects; override;
229 // value
230 procedure setStringValue(avalue: NSString); override;
231 function stringValue: NSString; override;
232 procedure addSubView(aview: NSView); override;
233
234 // this is parts of
235 procedure insertText_replacementRange (aString: id; replacementRange: NSRange);
236 procedure doCommandBySelector (aSelector: SEL); override;
237 procedure setMarkedText_selectedRange_replacementRange (aString: id; selectedRange: NSRange; replacementRange: NSRange);
238 procedure unmarkText;
239 function selectedRange: NSRange;
240 function markedRange: NSRange;
241 function hasMarkedText: LCLObjCBoolean;
242 function attributedSubstringForProposedRange_actualRange (aRange: NSRange; actualRange: NSRangePointer): NSAttributedString;
243 function validAttributesForMarkedText: NSArray;
244 function firstRectForCharacterRange_actualRange (aRange: NSRange; actualRange: NSRangePointer): NSRect;
245 function characterIndexForPoint (aPoint: NSPoint): NSUInteger;
246 end;
247
248 TStatusItemData = record
249 Text : NSString;
250 Width : Integer;
251 Align : TAlignment;
252 end;
253
254 TStatusItemDataArray = array of TStatusItemData;
255
256 { TCocoaStatusBar }
257
258 IStatusBarCallback = interface {(ICommonCallback) // not needed to inherit from ICommonCallback}
259 function GetBarsCount: Integer;
260 //todo: consider the use Cocoa native types, instead of FPC TAlignment
261 function GetBarItem(idx: Integer; var txt: String;
262 var width: Integer; var align: TAlignment): Boolean;
263 procedure DrawPanel(idx: Integer; const r: TRect);
264 end;
265
266 TCocoaStatusBar = objcclass(TCocoaCustomControl)
267 public
268 //StatusBar : TStatusBar;
269 barcallback : IStatusBarCallback;
270 panelCell : NSCell;
271 procedure drawRect(dirtyRect: NSRect); override;
272 procedure dealloc; override;
273 end;
274
275 { TCocoaGroupBox }
276
277 TCocoaGroupBox = objcclass(NSBox)
278 public
279 callback: ICommonCallback;
280 function acceptsFirstResponder: LCLObjCBoolean; override;
281 function lclGetCallback: ICommonCallback; override;
282 procedure lclClearCallback; override;
283 procedure resetCursorRects; override;
284 function lclClientFrame: TRect; override;
285 function lclContentView: NSView; override;
286 function lclGetFrameToLayoutDelta: TRect; override;
287 end;
288
289
290 const
291 PROGRESS_REG_HEIGHT = 16; // no longer applies on later macOS version
292 PROGRESS_SMALL_HEIGHT = 10;
293
294 type
295 { TCocoaProgressIndicator }
296
297 TCocoaProgressIndicator = objcclass(NSProgressIndicator)
298 callback: ICommonCallback;
299 function acceptsFirstResponder: LCLObjCBoolean; override;
300 function lclGetCallback: ICommonCallback; override;
301 procedure lclClearCallback; override;
302 procedure resetCursorRects; override;
303 function lclGetFrameToLayoutDelta: TRect; override;
304 procedure lclSetFrame(const r: TRect); override;
305 // mouse
306 function acceptsFirstMouse(event: NSEvent): LCLObjCBoolean; override;
307 procedure mouseDown(event: NSEvent); override;
308 procedure mouseUp(event: NSEvent); override;
309 procedure rightMouseDown(event: NSEvent); override;
310 procedure rightMouseUp(event: NSEvent); override;
311 procedure rightMouseDragged(event: NSEvent); override;
312 procedure otherMouseDown(event: NSEvent); override;
313 procedure otherMouseUp(event: NSEvent); override;
314 procedure otherMouseDragged(event: NSEvent); override;
315 procedure mouseDragged(event: NSEvent); override;
316 procedure mouseMoved(event: NSEvent); override;
317 procedure scrollWheel(event: NSEvent); override;
318 end;
319
320 { TManualTicks }
321
322 TManualTicks = class(TObject)
323 count : integer;
324 //todo: keep sorted and do binary search
325 ticks : array of Integer;
326 draw : Boolean;
327 function AddTick(atick: integer): Boolean;
328 end;
329
330 { TCocoaSlider }
331
332 TCocoaSlider = objcclass(NSSlider)
333 callback : ICommonCallback;
334 intval : Integer;
335 man : TManualTicks;
336
337 procedure dealloc; override;
338 procedure drawRect(dirtyRect: NSRect); override;
339
340 function acceptsFirstResponder: LCLObjCBoolean; override;
341 function lclGetCallback: ICommonCallback; override;
342 procedure lclClearCallback; override;
343 procedure resetCursorRects; override;
344 //
345 procedure SnapToInteger(AExtraFactor: Integer = 0); message 'SnapToInteger:';
346 procedure sliderAction(sender: id); message 'sliderAction:';
347 // mouse
348 function acceptsFirstMouse(event: NSEvent): LCLObjCBoolean; override;
349 procedure mouseDown(event: NSEvent); override;
350 procedure mouseUp(event: NSEvent); override;
351 procedure rightMouseDown(event: NSEvent); override;
352 procedure rightMouseUp(event: NSEvent); override;
353 procedure rightMouseDragged(event: NSEvent); override;
354 procedure otherMouseDown(event: NSEvent); override;
355 procedure otherMouseUp(event: NSEvent); override;
356 procedure otherMouseDragged(event: NSEvent); override;
357 procedure mouseDragged(event: NSEvent); override;
358 procedure mouseMoved(event: NSEvent); override;
359 procedure scrollWheel(event: NSEvent); override;
360
361 procedure lclAddManTick(atick : integer); message 'lclAddManTick:';
362 procedure lclSetManTickDraw(adraw: Boolean); message 'lclSetManTickDraw:';
363 procedure lclExpectedKeys(var wantTabs, wantArrows, wantReturn, wantAll: Boolean); override;
364 end;
365
366 TCocoaSliderCell = objcclass(NSSliderCell)
367 end;
368
369 procedure SetViewDefaults(AView: NSView);
370 function CheckMainThread: Boolean;
371 function GetNSViewSuperViewHeight(view: NSView): CGFloat;
372
373 procedure SetNSControlSize(ctrl: NSView; newHeight, miniHeight, smallHeight: Integer; AutoChangeFont: Boolean);
374
375 // these constants are missing from CocoaAll for some reason
376 const
377 NSTextAlignmentLeft = 0;
378 NSTextAlignmentRight = 1; // it's 2 for iOS and family
379 NSTextAlignmentCenter = 2; // it's 1 for iOS and family
380 NSTextAlignmentJustified = 3;
381 NSTextAlignmentNatural = 4;
382
383 var
384 // todo: this should be a threadvar
385 TrackedControl : NSObject = nil;
386
387 function isCallbackForSameObject(cb1, cb2: ICommonCallback): Boolean;
388
389 function NSViewIsLCLEnabled(v: NSView): Boolean;
390 function NSObjectIsLCLEnabled(obj: NSObject): Boolean;
391 function NSViewCanFocus(v: NSView): Boolean;
392
393 implementation
394
395 function NSObjectIsLCLEnabled(obj: NSObject): Boolean;
396 begin
397 if obj.isKindOfClass(NSView) then
398 Result := NSViewIsLCLEnabled(NSView(obj))
399 else
400 Result := obj.lclIsEnabled;
401 end;
402
403 function NSViewIsLCLEnabled(v: NSView): Boolean;
404 begin
405 Result := true;
406 while Assigned(v) do
407 begin
408 if not v.lclIsEnabled then begin
409 Result := false;
410 break;
411 end;
412 v:=v.superview;
413 end;
414 end;
415
416 function NSViewCanFocus(v: NSView): Boolean;
417 var
418 cb: ICommonCallback;
419 begin
420 if Assigned(v) then
421 begin
422 cb := v.lclGetCallback;
423 if Assigned(cb) then
424 Result := cb.CanFocus
425 else
426 Result := true;
427 end
428 else
429 Result := false;
430 end;
431
432 function isCallbackForSameObject(cb1, cb2: ICommonCallback): Boolean;
433 begin
434 Result := Assigned(cb1) and Assigned(cb2);
435 if Result then
436 Result := (cb1 = cb2) or (cb1.GetTarget = cb2.GetTarget);
437 end;
438
439 procedure SetViewDefaults(AView: NSView);
440 begin
441 if not Assigned(AView) then Exit;
442 AView.setAutoresizingMask(NSViewMinYMargin or NSViewMaxXMargin);
443 end;
444
445 function CheckMainThread: Boolean;
446 begin
447 Result := NSThread.currentThread.isMainThread;
448 end;
449
450 function GetNSViewSuperViewHeight(view: NSView): CGFloat;
451 begin
452 Result := -1;
453 if not Assigned(view) then Exit;
454 if not Assigned(view.superview) then Exit;
455 //if view.superview.isKindOfClass_(TCocoaTabPageView) then
456 //Result := TCocoaTabPageView(view.superview).tabview.contentRect.size.height
457 //else
458 Result := view.superview.frame.size.height;
459 {$IFDEF COCOA_SUPERVIEW_HEIGHT}
460 WriteLn(Format('GetNSViewSuperViewHeight Result=%f', [Result]));
461 {$ENDIF}
462 end;
463
464 { TManualTicks }
465
AddTicknull466 function TManualTicks.AddTick(atick: integer): Boolean;
467 var
468 i : integer;
469 begin
470 //todo: must be a binary search
471 for i:=0 to length(ticks)-1 do
472 if ticks[i]=atick then begin
473 Result:=false;
474 Exit;
475 end;
476
477 // adding new tick
478 if length(ticks)=count then begin
479 if count=0 then SetLength(ticks, 8)
480 else SetLength(ticks, count * 2);
481 end;
482 ticks[count]:=atick;
483 inc(count);
484 Result := true;
485 end;
486
487 { TCocoaGroupBox }
488
lclClientFramenull489 function TCocoaGroupBox.lclClientFrame: TRect;
490 var
491 v : NSView;
492 begin
493 v:=contentView;
494 if not Assigned(v) then
495 Result := inherited lclClientFrame
496 else
497 if v.isFlipped then
498 Result := NSRectToRect( v.frame )
499 else
500 NSToLCLRect(v.frame, frame.size.height, Result);
501 end;
502
lclContentViewnull503 function TCocoaGroupBox.lclContentView: NSView;
504 begin
505 Result := NSView(contentView);
506 end;
507
lclGetFrameToLayoutDeltanull508 function TCocoaGroupBox.lclGetFrameToLayoutDelta: TRect;
509 begin
510 Result.Left := 3;
511 Result.Right := -3;
512 Result.Top := 0;
513 Result.Bottom := -4;
514 end;
515
acceptsFirstRespondernull516 function TCocoaGroupBox.acceptsFirstResponder: LCLObjCBoolean;
517 begin
518 Result := True;
519 end;
520
lclGetCallbacknull521 function TCocoaGroupBox.lclGetCallback: ICommonCallback;
522 begin
523 Result := callback;
524 end;
525
526 procedure TCocoaGroupBox.lclClearCallback;
527 begin
528 callback := nil;
529 end;
530
531 procedure TCocoaGroupBox.resetCursorRects;
532 begin
533 if not Assigned(callback) or not callback.resetCursorRects then
534 inherited resetCursorRects;
535 end;
536
537 { TCocoaCustomControl }
538
539 procedure TCocoaCustomControl.setStringValue(avalue: NSString);
540 begin
541 if Assigned(fstr) then fstr.release;
542 if ASsigned(avalue) then
543 fstr:=avalue.copyWithZone(nil)
544 else
545 fstr:=nil;
546 inherited setStringValue(avalue);
547 end;
548
stringValuenull549 function TCocoaCustomControl.stringValue: NSString;
550 begin
551 Result:=fstr;
552 end;
553
554 procedure TCocoaCustomControl.addSubView(aview: NSView);
555 begin
556 inherited addSubView(aview);
557
558 if Assigned(aview) then
559 begin
560 // forcing LCL compatible "auto-move" mode. Sticking to left/top corner
561 if not autoresizesSubviews then
562 {$ifdef BOOLFIX}
563 setAutoresizesSubviews_(Ord(true));
564 {$else}
565 setAutoresizesSubviews(true);
566 {$endif}
567 aview.setAutoresizingMask(NSViewMaxXMargin or NSViewMinYMargin);
568 end;
569 end;
570
571 procedure TCocoaCustomControl.insertText_replacementRange(aString: id;
572 replacementRange: NSRange);
573 begin
574 lclGetCallback.InputClientInsertText(NSStringToString(NSString(astring)));
575 end;
576
577 procedure TCocoaCustomControl.doCommandBySelector(aSelector: SEL);
578 begin
579 inherited doCommandBySelector(ASelector);
580 end;
581
582 procedure TCocoaCustomControl.setMarkedText_selectedRange_replacementRange(
583 aString: id; selectedRange: NSRange; replacementRange: NSRange);
584 begin
585
586 end;
587
588 procedure TCocoaCustomControl.unmarkText;
589 begin
590 end;
591
selectedRangenull592 function TCocoaCustomControl.selectedRange: NSRange;
593 begin
594 Result := NSMakeRange(0,0);
595 end;
596
markedRangenull597 function TCocoaCustomControl.markedRange: NSRange;
598 begin
599 Result := NSMakeRange(0,0);
600 end;
601
hasMarkedTextnull602 function TCocoaCustomControl.hasMarkedText: LCLObjCBoolean;
603 begin
604 Result := false;
605 end;
606
attributedSubstringForProposedRange_actualRangenull607 function TCocoaCustomControl.attributedSubstringForProposedRange_actualRange(
608 aRange: NSRange; actualRange: NSRangePointer): NSAttributedString;
609 begin
610 Result := nil;
611 end;
612
validAttributesForMarkedTextnull613 function TCocoaCustomControl.validAttributesForMarkedText: NSArray;
614 begin
615 Result := nil;
616 end;
617
firstRectForCharacterRange_actualRangenull618 function TCocoaCustomControl.firstRectForCharacterRange_actualRange(
619 aRange: NSRange; actualRange: NSRangePointer): NSRect;
620 begin
621 Result := NSMakeRect(0,0,0,0);
622 end;
623
characterIndexForPointnull624 function TCocoaCustomControl.characterIndexForPoint(aPoint: NSPoint
625 ): NSUInteger;
626 begin
627 Result := 0;
628 end;
629
630 procedure TCocoaCustomControl.dealloc;
631 begin
632 if Assigned(fstr) then fstr.release;
633 inherited dealloc;
634 end;
635
acceptsFirstRespondernull636 function TCocoaCustomControl.acceptsFirstResponder: LCLObjCBoolean;
637 begin
638 Result := True;
639 end;
640
acceptsFirstMousenull641 function TCocoaCustomControl.acceptsFirstMouse(event: NSEvent): LCLObjCBoolean;
642 begin
643 // By default, a mouse-down event in a window that isn’t the key window
644 // simply brings the window forward and makes it key; the event isn’t sent
645 // to the NSView object over which the mouse click occurs. The NSView can
646 // claim an initial mouse-down event, however, by overriding acceptsFirstMouse: to return YES.
647 // see bug #33034
648 Result:=true;
649 end;
650
651 procedure TCocoaCustomControl.drawRect(dirtyRect: NSRect);
652 begin
653 if isdrawing=0 then faileddraw:=false;
654 inc(isdrawing);
655 inherited drawRect(dirtyRect);
656
657 // Implement Color property
658 if Assigned(callback) then
659 callback.DrawBackground(NSGraphicsContext.currentContext, bounds, dirtyRect);
660
661 if CheckMainThread and Assigned(callback) then
662 callback.Draw(NSGraphicsContext.currentContext, bounds, dirtyRect);
663 dec(isdrawing);
664
665 if (isdrawing=0) and (faileddraw) then
666 begin
667 // Similar to Carbon. Cocoa doesn't welcome changing a framerects during paint event
668 // If such thing happens, the results are pretty much inpredicatable. #32970
669 // TreeView tries to updatedScrollBars during paint event. That sometimes is causing
670 // the frame to be changed (i.e. scroll bar showed or hidden, resized the client rect)
671 // as a result, the final image is shown up-side-down.
672 //
673 // Below is an attempt to prevent graphical artifacts and to redraw
674 // the control again.
675 inherited drawRect(dirtyRect);
676
677 if Assigned(callback) then
678 callback.DrawBackground(NSGraphicsContext.currentContext, bounds, dirtyRect);
679
680 if CheckMainThread and Assigned(callback) then
681 callback.Draw(NSGraphicsContext.currentContext, bounds, dirtyRect);
682 end;
683 end;
684
TCocoaCustomControl.lclGetCallbacknull685 function TCocoaCustomControl.lclGetCallback: ICommonCallback;
686 begin
687 Result := callback;
688 end;
689
690 procedure TCocoaCustomControl.lclClearCallback;
691 begin
692 callback := nil;
693 end;
694
TCocoaCustomControl.lclIsMouseInAuxAreanull695 function TCocoaCustomControl.lclIsMouseInAuxArea(Event: NSevent): Boolean;
696 begin
697 if auxMouseByParent and Assigned(superview) then
698 Result := superview.lclIsMouseInAuxArea(Event)
699 else
700 Result := false;
701 end;
702
703 procedure TCocoaCustomControl.mouseDown(event: NSEvent);
704 begin
705 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
706 inherited mouseDown(event);
707 end;
708
709 procedure TCocoaCustomControl.mouseDragged(event: NSEvent);
710 begin
711 if not Assigned(callback) or not callback.MouseMove(event) then
712 // calling inherited causes the drag event to be passed to the
713 // parent controls
714
715 //inherited mouseDragged(event);
716 ;
717 end;
718
719 procedure TCocoaCustomControl.mouseEntered(event: NSEvent);
720 begin
721 inherited mouseEntered(event);
722 end;
723
724 procedure TCocoaCustomControl.mouseExited(event: NSEvent);
725 begin
726 inherited mouseExited(event);
727 end;
728
729 procedure TCocoaCustomControl.mouseMoved(event: NSEvent);
730 begin
731 if not Assigned(callback) or not callback.MouseMove(event) then
732 inherited mouseMoved(event);
733 end;
734
735 procedure TCocoaCustomControl.scrollWheel(event: NSEvent);
736 begin
737 if not Assigned(callback) or not callback.scrollWheel(event) then
738 inherited scrollWheel(event);
739 end;
740
741 procedure TCocoaCustomControl.setFrame(aframe: NSRect);
742 begin
743 if NSEqualRects(aframe, frame) then Exit;
744 if isdrawing>0 then
745 faileddraw := true;
746
747 inherited setFrame(aframe);
748 // it actually should come from a notifcation
749 if Assigned(callback) then callback.frameDidChange(self);
750 end;
751
752 procedure TCocoaCustomControl.mouseUp(event: NSEvent);
753 begin
754 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
755 inherited mouseUp(event);
756 end;
757
758 procedure TCocoaCustomControl.rightMouseDown(event: NSEvent);
759 begin
760 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
761 inherited rightMouseDown(event);
762 end;
763
764 procedure TCocoaCustomControl.rightMouseUp(event: NSEvent);
765 begin
766 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
767 inherited rightMouseUp(event);
768 end;
769
770 procedure TCocoaCustomControl.rightMouseDragged(event: NSEvent);
771 begin
772 if not Assigned(callback) or not callback.MouseMove(event) then
773 inherited rightMouseDragged(event);
774 end;
775
776 procedure TCocoaCustomControl.otherMouseDown(event: NSEvent);
777 begin
778 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
779 inherited otherMouseDown(event);
780 end;
781
782 procedure TCocoaCustomControl.otherMouseUp(event: NSEvent);
783 begin
784 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
785 inherited otherMouseUp(event);
786 end;
787
788 procedure TCocoaCustomControl.otherMouseDragged(event: NSEvent);
789 begin
790 if not Assigned(callback) or not callback.MouseMove(event) then
791 inherited otherMouseDragged(event);
792 end;
793
794 procedure TCocoaCustomControl.resetCursorRects;
795 begin
796 if not Assigned(callback) or not callback.resetCursorRects then
797 inherited resetCursorRects;
798 end;
799
800 { LCLObjectExtension }
801
LCLObjectExtension.lclIsEnablednull802 function LCLObjectExtension.lclIsEnabled: Boolean;
803 begin
804 Result := False;
805 end;
806
807 procedure LCLObjectExtension.lclSetEnabled(AEnabled: Boolean);
808 begin
809 end;
810
LCLObjectExtension.lclIsVisiblenull811 function LCLObjectExtension.lclIsVisible: Boolean;
812 begin
813 Result := False;
814 end;
815
816 procedure LCLObjectExtension.lclSetVisible(AVisible: Boolean);
817 begin
818 end;
819
LCLObjectExtension.lclWindowStatenull820 function LCLObjectExtension.lclWindowState: Integer;
821 begin
822 Result := SIZE_RESTORED;
823 end;
824
825 procedure LCLObjectExtension.lclInvalidateRect(const r: TRect);
826 begin
827 end;
828
829 procedure LCLObjectExtension.lclInvalidate;
830 begin
831 end;
832
833 procedure LCLObjectExtension.lclUpdate;
834 begin
835 end;
836
837 procedure LCLObjectExtension.lclRelativePos(var Left,Top: Integer);
838 begin
839 end;
840
841 procedure LCLObjectExtension.lclLocalToScreen(var X,Y: Integer);
842 begin
843 end;
844
845 procedure LCLObjectExtension.lclScreenToLocal(var X, Y: Integer);
846 begin
847 end;
848
LCLObjectExtension.lclParentnull849 function LCLObjectExtension.lclParent:id;
850 begin
851 Result:=nil;
852 end;
853
LCLObjectExtension.lclFramenull854 function LCLObjectExtension.lclFrame:TRect;
855 begin
856 FillChar(Result, sizeof(Result), 0);
857 end;
858
859 procedure LCLObjectExtension.lclSetFrame(const r:TRect);
860 begin
861
862 end;
863
LCLObjectExtension.lclGetFrameToLayoutDeltanull864 function LCLObjectExtension.lclGetFrameToLayoutDelta: TRect;
865 begin
866 Result.Top := 0;
867 Result.Left := 0;
868 Result.Right := 0;
869 Result.Bottom := 0;
870 end;
871
LCLObjectExtension.lclClientFramenull872 function LCLObjectExtension.lclClientFrame:TRect;
873 begin
874 FillChar(Result, sizeof(Result), 0);
875 end;
876
LCLObjectExtension.lclGetCallbacknull877 function LCLObjectExtension.lclGetCallback: ICommonCallback;
878 begin
879 Result := nil;
880 end;
881
882 procedure LCLObjectExtension.lclClearCallback;
883 begin
884 end;
885
LCLObjectExtension.lclGetPropStoragenull886 function LCLObjectExtension.lclGetPropStorage: TStringList;
887 var
888 Callback: ICommonCallback;
889 begin
890 Callback := lclGetCallback;
891 if Assigned(Callback) then
892 Result := Callback.GetPropStorage
893 else
894 Result := nil;
895 end;
896
LCLObjectExtension.lclGetTargetnull897 function LCLObjectExtension.lclGetTarget: TObject;
898 var
899 Callback: ICommonCallback;
900 begin
901 Callback := lclGetCallback;
902 if Assigned(Callback) then
903 Result := Callback.GetTarget
904 else
905 Result := nil;
906 end;
907
LCLObjectExtension.lclDeliverMessagenull908 function LCLObjectExtension.lclDeliverMessage(Msg: Cardinal; WParam: WParam; LParam: LParam): LResult;
909 var
910 Callback: ICommonCallback;
911 begin
912 Callback := lclGetCallback;
913 if Assigned(Callback) then
914 Result := Callback.DeliverMessage(Msg, WParam, LParam)
915 else
916 Result := 0;
917 end;
918
LCLObjectExtension.lclContentViewnull919 function LCLObjectExtension.lclContentView: NSView;
920 begin
921 Result := nil;
922 end;
923
924 procedure LCLObjectExtension.lclOffsetMousePos(var Point: NSPoint);
925 begin
926
927 end;
928
929 procedure LCLObjectExtension.lclExpectedKeys(var wantTabs, wantArrows,
930 wantReturn, wantAll: Boolean);
931 begin
932 wantTabs := false;
933 wantArrows := false;
934 wantReturn := false;
935 wantAll := false;
936 end;
937
938 { The method should return TRUE, if mouse is located above an auxilary area
939 of a (composited) control, and thus MOUSE MOVE event should not be propagated
940 to LCL. For example, controls with Scrollbars should not report mouse events
941 if mouse cursor is above ScrollBar and scroll bar is visible. (ScrollBar = Auxillary area)
942
943 By default, the whole area is considered to be non-auxillary and must be
944 reported to LCL.
945 }
LCLObjectExtension.lclIsMouseInAuxAreanull946 function LCLObjectExtension.lclIsMouseInAuxArea(Event: NSEvent): Boolean;
947 begin
948 Result := false;
949 end;
950
951 { LCLControlExtension }
952
RectToViewCoordnull953 function RectToViewCoord(view: NSView; const r: TRect): NSRect;
954 var
955 b: NSRect;
956 begin
957 b := view.bounds;
958 Result.origin.x := r.Left;
959 Result.size.width := r.Right - r.Left;
960 Result.size.height := r.Bottom - r.Top;
961 if Assigned(view) and (view.isFlipped) then
962 Result.origin.y := r.Top
963 else
964 Result.origin.y := b.size.height - r.Bottom;
965 end;
966
LCLControlExtension.lclIsEnablednull967 function LCLControlExtension.lclIsEnabled:Boolean;
968 begin
969 Result := IsEnabled;
970 end;
971
972 procedure LCLControlExtension.lclSetEnabled(AEnabled:Boolean);
973 begin
974 {$ifdef BOOLFIX}
975 SetEnabled_( Ord(AEnabled and NSViewIsLCLEnabled(self.superview) ));
976 {$else}
977 SetEnabled( AEnabled and NSViewIsLCLEnabled(self.superview) );
978 {$endif}
979 inherited lclSetEnabled(AEnabled);
980 end;
981
LCLViewExtension.lclInitWithCreateParamsnull982 function LCLViewExtension.lclInitWithCreateParams(const AParams: TCreateParams): id;
983 var
984 p: NSView;
985 ns: NSRect;
986 {$IFDEF COCOA_DEBUG_SETBOUNDS}
987 pstr: string;
988 {$ENDIF}
989 begin
990 p := nil;
991 if (AParams.WndParent <> 0) then
992 p := NSView(AParams.WndParent).lclContentView;
993
994 if Assigned(p) then
995 LCLToNSRect(Types.Bounds(AParams.X, AParams.Y, AParams.Width, AParams.Height),
996 p.frame.size.height, ns)
997 else
998 ns := GetNSRect(AParams.X, AParams.Y, AParams.Width, AParams.Height);
999
1000 {$IFDEF COCOA_DEBUG_SETBOUNDS}
1001 if Assigned(p) then
1002 begin
1003 pstr := NSStringToString(p.className);
1004 if NSStringToString(NSObject(AParams.WndParent).className) = 'TCocoaTabPage' then
1005 pstr := pstr + ' ' + NSStringToString(TCocoaTabPage(AParams.WndParent).label_);
1006 end
1007 else
1008 pstr := '';
1009 WriteLn(Format('[LCLViewExtension.lclInitWithCreateParams] Class=%s Caption=%s ParentClass=%s ParentClassView=%s rect=%d %d %d %d Visible=%d',
1010 [NSStringToString(Self.className), AParams.Caption,
1011 NSStringToString(NSObject(AParams.WndParent).className), pstr,
1012 Round(ns.Origin.x), Round(ns.Origin.y), Round(ns.size.width), Round(ns.size.height),
1013 AParams.Style and WS_VISIBLE]));
1014 {$ENDIF}
1015
1016 Result := initWithFrame(ns);
1017 if not Assigned(Result) then
1018 Exit;
1019
1020 {$ifdef BOOLFIX}
1021 setHidden_(Ord(AParams.Style and WS_VISIBLE = 0));
1022 {$else}
1023 setHidden(AParams.Style and WS_VISIBLE = 0);
1024 {$endif}
1025
1026 if Assigned(p) then
1027 p.lclContentView.addSubview(Result);
1028 SetViewDefaults(Result);
1029 end;
1030
LCLViewExtension.lclIsEnablednull1031 function LCLViewExtension.lclIsEnabled: Boolean;
1032 begin
1033 Result := true;
1034 end;
1035
1036 procedure LCLViewExtension.lclSetEnabled(AEnabled: Boolean);
1037 var
1038 cb : ICommonCallback;
1039 obj : NSObject;
1040 begin
1041 for obj in subviews do begin
1042 cb := obj.lclGetCallback;
1043 obj.lclSetEnabled(AEnabled and ((not Assigned(cb)) or cb.GetShouldBeEnabled) );
1044 end;
1045 end;
1046
LCLViewExtension.lclIsVisiblenull1047 function LCLViewExtension.lclIsVisible: Boolean;
1048 begin
1049 Result := not isHidden;
1050 end;
1051
1052 procedure LCLViewExtension.lclSetVisible(AVisible: Boolean);
1053 begin
1054 {$ifdef BOOLFIX}
1055 setHidden_(Ord(not AVisible));
1056 {$else}
1057 setHidden(not AVisible);
1058 {$endif}
1059 {$IFDEF COCOA_DEBUG_SETBOUNDS}
1060 WriteLn(Format('LCLViewExtension.lclSetVisible: %s AVisible=%d',
1061 [NSStringToString(Self.ClassName), Integer(AVisible)]));
1062 {$ENDIF}
1063 end;
1064
LCLViewExtension.lclIsPaintingnull1065 function LCLViewExtension.lclIsPainting: Boolean;
1066 begin
1067 Result := Assigned(lclGetCallback) and Assigned(lclGetCallback.GetContext);
1068 end;
1069
1070 procedure LCLViewExtension.lclInvalidateRect(const r:TRect);
1071 var
1072 view : NSView;
1073 begin
1074 view:=lclContentView;
1075 if Assigned(view) then
1076 view.setNeedsDisplayInRect(RectToViewCoord(view, r))
1077 else
1078 self.setNeedsDisplayInRect(RectToViewCoord(Self, r));
1079 //todo: it might be necessary to always invalidate self
1080 // just need to get offset of the contentView relative for self
1081 end;
1082
1083 procedure LCLViewExtension.lclInvalidate;
1084 begin
1085 {$ifdef BOOLFIX}
1086 setNeedsDisplay__(Ord(True));
1087 {$else}
1088 setNeedsDisplay_(True);
1089 {$endif}
1090 end;
1091
1092 procedure LCLViewExtension.lclUpdate;
1093 begin
1094 {$ifdef BOOLFIX}
1095 setNeedsDisplay__(Ord(True));
1096 {$else}
1097 setNeedsDisplay_(True);
1098 {$endif}
1099 //display;
1100 end;
1101
1102 procedure LCLViewExtension.lclRelativePos(var Left, Top: Integer);
1103 var
1104 sv : NSView;
1105 fr : NSRect;
1106 begin
1107 Left := Round(frame.origin.x);
1108 sv := superview;
1109 if Assigned(sv) and (not sv.isFlipped) then
1110 begin
1111 fr := frame;
1112 Top := Round(sv.frame.size.height - fr.origin.y - fr.size.height);
1113 end
1114 else
1115 Top := Round(frame.origin.y);
1116 end;
1117
1118 procedure LCLViewExtension.lclLocalToScreen(var X, Y:Integer);
1119 var
1120 P: NSPoint;
1121
1122 begin
1123 // 1. convert to window base
1124 // Convert from View-lcl to View-cocoa
1125 P.x := X;
1126 if isFlipped then
1127 p.y := Y
1128 else
1129 P.y := frame.size.height-y; // convert to Cocoa system
1130
1131 // Convert from View-cocoa to Window-cocoa
1132 P := convertPoint_ToView(P, nil);
1133
1134 // Convert from Window-cocoa to Window-lcl
1135 X := Round(P.X);
1136 Y := Round(window.frame.size.height-P.Y); // convert to LCL system
1137
1138 // 2. convert window to screen
tonull1139 // Use window function to convert fomr Window-lcl to Screen-lcl
1140 window.lclLocalToScreen(X, Y);
1141 end;
1142
1143 procedure LCLViewExtension.lclScreenToLocal(var X, Y: Integer);
1144 var
1145 P: NSPoint;
1146 begin
1147 // 1. convert from screen to window
tonull1148 // use window function to onvert from Screen-lcl to Window-lcl
1149 window.lclScreenToLocal(X, Y);
1150 // Convert from Window-lcl to Window-cocoa
1151 P.x := X;
1152 P.y := Round(window.frame.size.height-Y); // convert to Cocoa system
1153
1154 // 2. convert from window to local
1155 // Convert from Window-cocoa to View-cocoa
1156 P := convertPoint_FromView(P, nil);
1157
1158 // Convert from View-cocoa to View-lcl
1159 X := Round(P.x);
1160 if isFlipped then
1161 Y := Round(p.y)
1162 else
1163 Y := Round(frame.size.height-P.y); // convert to Cocoa system
1164 end;
1165
LCLViewExtension.lclParentnull1166 function LCLViewExtension.lclParent:id;
1167 begin
1168 Result := superView;
1169 end;
1170
LCLViewExtension.lclFramenull1171 function LCLViewExtension.lclFrame: TRect;
1172 var
1173 v: NSView;
1174 begin
1175 v := superview;
1176 if Assigned(v) and not v.isFlipped then
1177 NSToLCLRect(frame, v.frame.size.height, Result)
1178 else
1179 Result := NSRectToRect(frame);
1180 AddLayoutToFrame( lclGetFrameToLayoutDelta, Result);
1181 end;
1182
1183 procedure LCLViewExtension.lclSetFrame(const r: TRect);
1184 var
1185 ns: NSRect;
1186 svHeight: CGFloat;
1187 rr : TRect;
1188 begin
1189 rr := r;
1190 SubLayoutFromFrame( lclGetFrameToLayoutDelta, rr);
1191
1192 svHeight := GetNSViewSuperViewHeight(Self);
1193 if Assigned(superview) and not superview.isFlipped then
1194 begin
1195 LCLToNSRect(rr, svHeight, ns)
1196 end
1197 else
1198 ns := RectToNSRect(rr);
1199
1200 {$IFDEF COCOA_DEBUG_SETBOUNDS}
1201 WriteLn(Format('LCLViewExtension.lclSetFrame: %s Bounds=%s height=%d ns_pos=%d %d ns_size=%d %d',
1202 [NSStringToString(Self.ClassName), dbgs(r), Round(svHeight),
1203 Round(ns.origin.x), Round(ns.origin.y), Round(ns.size.width), Round(ns.size.height)]));
1204 {$ENDIF}
1205 setFrame(ns);
1206 end;
1207
LCLViewExtension.lclClientFramenull1208 function LCLViewExtension.lclClientFrame: TRect;
1209 begin
1210 Result := lclFrame;
1211 Types.OffsetRect(Result, -Result.Left, -Result.Top);
1212 end;
1213
LCLViewExtension.lclContentViewnull1214 function LCLViewExtension.lclContentView: NSView;
1215 begin
1216 Result := self;
1217 end;
1218
1219 procedure LCLViewExtension.lclOffsetMousePos(var Point: NSPoint);
1220 var
1221 es : NSScrollView;
1222 r : NSRect;
1223 dlt : TRect;
1224 begin
1225 Point := convertPoint_fromView(Point, nil);
1226
1227 es := enclosingScrollView;
1228 if es.documentView <> self then es := nil;
1229 if not isFlipped then
1230 Point.y := bounds.size.height - Point.y;
1231
1232 if Assigned(es) then
1233 begin
1234 r := es.documentVisibleRect;
1235 if isFlipped then
1236 Point.y := Point.y - r.origin.y
1237 else
1238 Point.y := Point.y - (es.documentView.frame.size.height - r.size.height - r.origin.y);
1239 Point.X := Point.X - r.origin.x;
1240 end;
1241
1242 dlt := lclGetFrameToLayoutDelta;
1243 Point.X := Point.X - dlt.Left;
1244 Point.Y := Point.Y - dlt.Top;
1245 end;
1246
1247 { TCocoaStatusBar }
1248
1249 procedure TCocoaStatusBar.drawRect(dirtyRect: NSRect);
1250 var
1251 R : TRect;
1252 i : Integer;
1253 cs : NSString;
1254 nr : NSRect;
1255 dr : NSRect;
1256 al : TAlignment;
1257 x : Integer;
1258 txt : string;
1259 cnt : Integer;
1260 w : Integer;
1261 const
1262 CocoaAlign: array [TAlignment] of Integer = (NSNaturalTextAlignment, NSRightTextAlignment, NSCenterTextAlignment);
1263 begin
1264 if not Assigned(barcallback) then Exit;
1265
1266 if not Assigned(panelCell) then Exit;
1267
1268 panelCell.setControlView(Self);
1269
1270 r := lclClientFrame();
1271 nr.origin.y := 0;
1272 nr.size.height := self.lclFrame.Height;
1273
1274 x:=0;
1275 cnt := barcallback.GetBarsCount;
1276 for i:=0 to cnt - 1 do begin
1277
1278 txt := '';
1279 w := 0;
1280 al := taLeftJustify;
1281
1282 if not barcallback.GetBarItem(i, txt, w, al) then Continue;
1283
1284 if i = cnt - 1 then w := r.Right - x;
1285 nr.size.width := w;
1286 nr.origin.x := x;
1287
1288 // dr - draw rect. should be 1 pixel wider
1289 // and 1 pixel taller, than the actual rect.
1290 // to produce a better visual effect
1291 dr := nr;
1292 dr.size.width := dr.size.width + 1;
1293 dr.size.height := dr.size.height + 1;
1294 dr.origin.y := dr.origin.y-1;
1295
1296 cs := NSStringUtf8(txt);
1297 panelCell.setTitle(cs);
1298 panelCell.setAlignment(CocoaAlign[al]);
1299 panelCell.drawWithFrame_inView(dr, Self);
1300 cs.release;
1301 barcallback.DrawPanel(i, NSRectToRect(nr));
1302 inc(x, w);
1303 if x > r.Right then break; // no place left
1304 end;
1305 end;
1306
1307 procedure TCocoaStatusBar.dealloc;
1308 begin
1309 if Assigned(panelCell) then panelCell.release;
1310 inherited;
1311 end;
1312
1313 { TCocoaProgressIndicator }
1314
TCocoaProgressIndicator.acceptsFirstRespondernull1315 function TCocoaProgressIndicator.acceptsFirstResponder: LCLObjCBoolean;
1316 begin
1317 Result:=True;
1318 end;
1319
lclGetCallbacknull1320 function TCocoaProgressIndicator.lclGetCallback: ICommonCallback;
1321 begin
1322 Result:=callback;
1323 end;
1324
1325 procedure TCocoaProgressIndicator.lclClearCallback;
1326 begin
1327 callback:=nil;
1328 end;
1329
1330 procedure TCocoaProgressIndicator.resetCursorRects;
1331 begin
1332 if not callback.resetCursorRects then
1333 inherited resetCursorRects;
1334 end;
1335
lclGetFrameToLayoutDeltanull1336 function TCocoaProgressIndicator.lclGetFrameToLayoutDelta: TRect;
1337 begin
1338 case controlSize of
1339 NSSmallControlSize, NSMiniControlSize:
1340 begin
1341 Result.Left := 1;
1342 Result.Right := -1;
1343 Result.Top := 0;
1344 Result.Bottom := -2;
1345 end;
1346 else
1347 Result.Left := 2;
1348 Result.Right := -2;
1349 Result.Top := 0;
1350 Result.Bottom := -4;
1351 end;
1352 end;
1353
1354 procedure TCocoaProgressIndicator.lclSetFrame(const r: TRect);
1355 begin
1356 SetNSControlSize(self, r.Bottom - r.Top, 0, PROGRESS_SMALL_HEIGHT, true);
1357 inherited lclSetFrame(r);
1358 end;
1359
TCocoaProgressIndicator.acceptsFirstMousenull1360 function TCocoaProgressIndicator.acceptsFirstMouse(event: NSEvent): LCLObjCBoolean;
1361 begin
1362 Result:=true;
1363 end;
1364
1365 procedure TCocoaProgressIndicator.mouseDown(event: NSEvent);
1366 begin
1367 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1368 begin
1369 inherited mouseDown(event);
1370
1371 callback.MouseUpDownEvent(event, true);
1372 end;
1373 end;
1374
1375 procedure TCocoaProgressIndicator.mouseUp(event: NSEvent);
1376 begin
1377 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1378 inherited mouseUp(event);
1379 end;
1380
1381 procedure TCocoaProgressIndicator.rightMouseDown(event: NSEvent);
1382 begin
1383 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1384 inherited rightMouseDown(event);
1385 end;
1386
1387 procedure TCocoaProgressIndicator.rightMouseUp(event: NSEvent);
1388 begin
1389 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1390 inherited rightMouseUp(event);
1391 end;
1392
1393 procedure TCocoaProgressIndicator.rightMouseDragged(event: NSEvent);
1394 begin
1395 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1396 inherited rightMouseDragged(event);
1397 end;
1398
1399 procedure TCocoaProgressIndicator.otherMouseDown(event: NSEvent);
1400 begin
1401 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1402 inherited otherMouseDown(event);
1403 end;
1404
1405 procedure TCocoaProgressIndicator.otherMouseUp(event: NSEvent);
1406 begin
1407 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1408 inherited otherMouseUp(event);
1409 end;
1410
1411 procedure TCocoaProgressIndicator.otherMouseDragged(event: NSEvent);
1412 begin
1413 if not Assigned(callback) or not callback.MouseMove(event) then
1414 inherited otherMouseDragged(event);
1415 end;
1416
1417 procedure TCocoaProgressIndicator.mouseDragged(event: NSEvent);
1418 begin
1419 if not Assigned(callback) or not callback.MouseMove(event) then
1420 inherited mouseDragged(event);
1421 end;
1422
1423 procedure TCocoaProgressIndicator.mouseMoved(event: NSEvent);
1424 begin
1425 if not Assigned(callback) or not callback.MouseMove(event) then
1426 inherited mouseMoved(event);
1427 end;
1428
1429 procedure TCocoaProgressIndicator.scrollWheel(event: NSEvent);
1430 begin
1431 if not Assigned(callback) or not callback.scrollWheel(event) then
1432 inherited scrollWheel(event);
1433 end;
1434
1435
1436 { TCocoaSlider }
1437
GetManTicksnull1438 function GetManTicks(slider: TCocoaSlider): TManualTicks;
1439 begin
1440 if not Assigned(slider.man) then
1441 slider.man := TManualTicks.Create;
1442 Result := slider.man;
1443 end;
1444
1445 procedure TCocoaSlider.dealloc;
1446 begin
1447 man.Free;
1448 inherited dealloc;
1449 end;
1450
1451 procedure TCocoaSlider.drawRect(dirtyRect: NSRect);
1452 var
1453 i : integer;
1454 nr : NSRect;
1455 xr : NSRect;
1456 dr : NSRect;
1457 nm : integer;
1458 ctx : NSGraphicsContext;
1459 pth : NSBezierPath;
1460 begin
1461 if not Assigned(man) or (not man.draw) then begin
1462 inherited drawRect(dirtyRect);
1463 Exit;
1464 end;
1465
1466 nm := round(maxValue - minValue);
1467 if nm = 0 then Exit;
1468 if numberOfTickMarks < 2 then Exit;
1469
1470 nr := rectOfTickMarkAtIndex(0);
1471 xr := rectOfTickMarkAtIndex(1);
1472
1473 ctx := NSGraphicsContext.currentContext;
1474 pth := NSBezierPath.bezierPath;
1475 NSColor.controlShadowColor.setFill;
1476 dr:=nr;
1477 dr.origin.y := dr.origin.y + 1;
1478 dr.size.height := dr.size.height - 1;
1479 for i := 0 to man.count - 1 do begin
1480 dr.origin.x := round(nr.origin.x + (xr.origin.x - nr.origin.x) * (man.ticks[i] - minValue) / nm);
1481 pth.fillRect(dr);
1482 end;
1483 inherited drawRect(dirtyRect);
1484 end;
1485
TCocoaSlider.acceptsFirstRespondernull1486 function TCocoaSlider.acceptsFirstResponder: LCLObjCBoolean;
1487 begin
1488 Result := True;
1489 end;
1490
lclGetCallbacknull1491 function TCocoaSlider.lclGetCallback: ICommonCallback;
1492 begin
1493 Result:=callback;
1494 end;
1495
1496 procedure TCocoaSlider.lclClearCallback;
1497 begin
1498 callback := nil;
1499 end;
1500
1501 procedure TCocoaSlider.resetCursorRects;
1502 begin
1503 if not callback.resetCursorRects then
1504 inherited resetCursorRects;
1505 end;
1506
1507 procedure TCocoaSlider.SnapToInteger(AExtraFactor: Integer);
1508 begin
1509 setIntValue(Round(doubleValue() + AExtraFactor));
1510 end;
1511
1512 procedure TCocoaSlider.sliderAction(sender: id);
1513 var
1514 newval: Integer;
1515 begin
1516 SnapToInteger();
1517 newval := intValue;
1518 if newval <> intval then begin
1519 intval := newval;
1520 // OnChange event
1521 if callback <> nil then
1522 callback.SendOnChange();
1523 end;
1524 end;
1525
acceptsFirstMousenull1526 function TCocoaSlider.acceptsFirstMouse(event: NSEvent): LCLObjCBoolean;
1527 begin
1528 Result:=true;
1529 end;
1530
1531 procedure TCocoaSlider.mouseDown(event: NSEvent);
1532 begin
1533 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1534 begin
1535 inherited mouseDown(event);
1536
1537 callback.MouseUpDownEvent(event, true);
1538 end;
1539 end;
1540
1541 procedure TCocoaSlider.mouseUp(event: NSEvent);
1542 begin
1543 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1544 inherited mouseUp(event);
1545 end;
1546
1547 procedure TCocoaSlider.rightMouseDown(event: NSEvent);
1548 begin
1549 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1550 inherited rightMouseDown(event);
1551 end;
1552
1553 procedure TCocoaSlider.rightMouseUp(event: NSEvent);
1554 begin
1555 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1556 inherited rightMouseUp(event);
1557 end;
1558
1559 procedure TCocoaSlider.rightMouseDragged(event: NSEvent);
1560 begin
1561 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1562 inherited rightMouseDragged(event);
1563 end;
1564
1565 procedure TCocoaSlider.otherMouseDown(event: NSEvent);
1566 begin
1567 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1568 inherited otherMouseDown(event);
1569 end;
1570
1571 procedure TCocoaSlider.otherMouseUp(event: NSEvent);
1572 begin
1573 if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
1574 inherited otherMouseUp(event);
1575 end;
1576
1577 procedure TCocoaSlider.otherMouseDragged(event: NSEvent);
1578 begin
1579 if not Assigned(callback) or not callback.MouseMove(event) then
1580 inherited otherMouseDragged(event);
1581 end;
1582
1583 procedure TCocoaSlider.mouseDragged(event: NSEvent);
1584 begin
1585 if not Assigned(callback) or not callback.MouseMove(event) then
1586 inherited mouseDragged(event);
1587 end;
1588
1589 procedure TCocoaSlider.mouseMoved(event: NSEvent);
1590 begin
1591 if not Assigned(callback) or not callback.MouseMove(event) then
1592 inherited mouseMoved(event);
1593 end;
1594
1595 procedure TCocoaSlider.scrollWheel(event: NSEvent);
1596 begin
1597 if not Assigned(callback) or not callback.scrollWheel(event) then
1598 inherited scrollWheel(event);
1599 end;
1600
1601 procedure TCocoaSlider.lclAddManTick(atick: integer);
1602 var
1603 mn : TManualTicks;
1604 begin
1605 mn := GetManTicks(self);
1606 if mn.AddTick(atick) then
1607 begin
1608 if mn.draw then self.setNeedsDisplay_(true);
1609 end;
1610 end;
1611
1612 procedure TCocoaSlider.lclSetManTickDraw(adraw: Boolean);
1613 var
1614 mn : TManualTicks;
1615 begin
1616 mn := GetManTicks(self);
1617 if mn.draw=adraw then Exit;
1618 mn.draw:=adraw;
1619 self.setNeedsDisplay_(true);
1620 end;
1621
1622 procedure TCocoaSlider.lclExpectedKeys(var wantTabs, wantArrows, wantReturn,
1623 wantAll: Boolean);
1624 begin
1625 wantTabs := false;
1626 wantArrows := true;
1627 wantReturn := false;
1628 wantAll := false;
1629 end;
1630
1631 type
1632 NSViewControlSizeExt = objccategory external (NSView)
controlSizenull1633 function controlSize: Integer; message 'controlSize';
1634 procedure setControlSize(ASize: Integer); message 'setControlSize:';
cellnull1635 function cell: id; message 'cell';
1636 procedure setFont(afont: NSFont); message 'setFont:';
1637 end;
1638
1639 procedure SetNSControlSize(ctrl: NSView; newHeight, miniHeight, smallHeight: Integer; AutoChangeFont: Boolean);
1640 var
1641 sz : NSControlSize;
1642 begin
1643 if (miniHeight>0) and (newHeight<=miniHeight) then
1644 sz:=NSMiniControlSize
1645 else if (smallHeight>0) and (newHeight<=smallHeight) then
1646 sz:=NSSmallControlSize
1647 else
1648 sz:=NSRegularControlSize;
1649
1650 if ctrl.respondsToSelector(ObjCSelector('setControlSize:')) then
1651 ctrl.setControlSize(sz)
1652 else if ctrl.respondsToSelector(ObjCSelector('cell')) then
1653 begin
1654 if NSCell(ctrl.cell).controlSize<>sz then
1655 NSCell(ctrl.cell).setControlSize(sz);
1656 end;
1657 if AutoChangeFont and (ctrl.respondsToSelector(ObjCSelector('setFont:'))) then
1658 ctrl.setFont(NSFont.systemFontOfSize(NSFont.systemFontSizeForControlSize(sz)));
1659 end;
1660
1661
1662 end.
1663
1664