2 classvar <globalKeyDownAction, <globalKeyUpAction;
6 classvar <currentDrag, <currentDragString;
8 var wasRemoved = false;
10 var <font, <resize = 1, <alpha = 1.0;
12 var <decorator, <layout;
14 var <>userCanClose=true, <>deleteOnClose = true;
17 var <mouseDownAction, <mouseUpAction, <mouseOverAction, <mouseLeaveAction;
18 var <mouseMoveAction, <mouseWheelAction;
19 var <keyDownAction, <keyUpAction, <keyModifiersChangedAction;
22 var <focusGainedAction, <focusLostAction;
25 var <beginDragAction, <canReceiveDragHandler, <receiveDragHandler;
27 var <toFrontAction, <endFrontAction;
32 hSizePolicy = [1,2,3,1,2,3,1,2,3];
33 vSizePolicy = [1,1,1,2,2,2,3,3,3];
36 *new { arg parent, bounds;
37 var p = parent.asView;
38 ^super.new( [p, bounds.asRect] ).initQView( p );
41 *newCustom { arg customArgs;
42 ^super.new( customArgs ).initQView( nil );
45 *qtClass { ^'QcDefaultWidget' }
51 ^this.primitiveFailed;
57 this.children.do { |child| child.remove };
60 mapToGlobal { arg point;
62 ^this.primitiveFailed;
65 // ----------------- properties --------------------------
68 this.setProperty( \font, f );
71 toolTip { ^this.getProperty(\toolTip) }
72 toolTip_ { arg t; this.setProperty( \toolTip, t ) }
75 ^this.getProperty( \palette );
79 this.setProperty( \palette, p );
83 ^this.palette.windowColor;
86 background_ { arg color;
87 this.setProperty( \palette, this.palette.windowColor_(color) );
88 this.setProperty( \autoFillBackground, true );
91 // NOTE: only for backwards compatibility
92 backColor_ { arg color;
93 this.background = color;
97 ^this.bounds.moveToPoint( this.mapToGlobal( 0@0 ) );
101 ^this.getProperty(\geometry)
105 this.setProperty(\geometry, rect.asRect )
108 sizeHint { ^this.getProperty(\sizeHint) }
110 minSizeHint { ^this.getProperty(\minimumSizeHint) }
112 // a Point can be passed instead of a Size
114 var max = QLimits(\maxWidgetSize);
116 this.setProperty( \maximumSize, Size( min(max,size.width), min(max,size.height) ) );
119 // a Point can be passed instead of a Size
120 minSize_ { arg size; this.setProperty( \minimumSize, size.asSize ); }
122 fixedSize_ { arg size;
124 this.setProperty( \minimumSize, size );
125 this.setProperty( \maximumSize, size );
128 maxWidth_ { arg width;
129 this.setProperty( \maximumWidth, min( width, QLimits(\maxWidgetSize) ) );
132 minWidth_ { arg width; this.setProperty( \minimumWidth, width ); }
134 maxHeight_ { arg height;
135 this.setProperty( \maximumHeight, min( height, QLimits(\maxWidgetSize) ) );
138 minHeight_ { arg height; this.setProperty( \minimumHeight, height ); }
140 // backwards compatibility
141 relativeOrigin { ^true }
144 this.bounds_( this.bounds.moveTo( x, y ) );
147 resizeTo { arg width, height;
148 this.bounds_( this.bounds.resizeTo( width, height ) );
152 ^this.getProperty(\visible)
155 this.setProperty(\visible, bool, false)
159 ^this.getProperty(\enabled)
162 this.setProperty(\enabled, bool)
166 this.setProperty(\_qc_hSizePolicy, hSizePolicy[anInt-1]);
167 this.setProperty(\_qc_vSizePolicy, vSizePolicy[anInt-1]);
171 var policy = this.getProperty(\focusPolicy);
175 canFocus_ { arg bool;
177 if( bool ) { policy = 16r1 | 16r2 | 16r8 } { policy = 0 };
178 this.setProperty(\focusPolicy, policy);
181 focus { arg flag=true;
183 ^this.primitiveFailed;
187 ^this.getProperty( \focus );
191 this.nonimpl( "focusColor_" );
195 this.nonimpl( "focusColor" );
199 // ------------------ container stuff ----------------------------
201 children { arg class = QView;
202 var ch = super.children( class );
203 ^ch.select { |v| (v.tryPerform(\isClosed) ? false).not };
206 parent { arg class = QView;
207 if (wasRemoved) { ^nil } { ^super.parent(class) };
213 if (wasRemoved.not) {
216 allParents = allParents.add( p );
228 var childWidgets = this.children( QView );
229 childWidgets.do { |child| child.remove };
232 layout_ { arg newLayout;
233 if( newLayout.notNil && (newLayout != layout) ) {
234 this.prSetLayout( newLayout );
239 addFlowLayout { arg margin, gap;
240 this.decorator_( FlowLayout( this.bounds.moveTo(0, 0), margin, gap ) );
244 decorator_ { arg decor;
245 decor.bounds = decor.bounds.moveTo(0, 0);
250 flow { arg func, bounds;
252 f = FlowView( this, bounds );
258 // ................. top window stuff ............................
261 ^this.getProperty( \windowTitle );
265 this.setProperty( \windowTitle, string );
270 ^this.primitiveFailed;
274 if( this.visible ) { this.invokeMethod( \showMinimized, synchronous:false ) };
278 if( this.getProperty( \minimized ) ) { this.invokeMethod( \showNormal, synchronous:false ) };
282 this.invokeMethod( \showFullScreen, synchronous:false );
286 if( this.getProperty( \fullScreen ) ) { this.invokeMethod( \showNormal, synchronous:false ) };
291 this.setProperty( \windowOpacity, aFloat );
295 _QWidget_GetAlwaysOnTop
296 ^this.primitiveFailed;
299 alwaysOnTop_ { arg boolean;
300 _QWidget_SetAlwaysOnTop
301 ^this.primitiveFailed;
307 { this.visible_( false ); }
311 if (wasRemoved) {^true} {^this.isValid.not};
314 notClosed { ^this.isClosed.not }
316 // ----------------- actions .....................................
319 // NOTE: not all widgets have action() signal
321 this.manageMethodConnection( action, func, 'action()', \doAction );
326 addAction { arg func, selector=\action;
327 this.perform(selector.asSetter, this.perform(selector).addFunc(func));
330 removeAction { arg func, selector=\action;
331 this.perform(selector.asSetter, this.perform(selector).removeFunc(func));
334 *globalKeyDownAction_ { arg action;
335 globalKeyDownAction = action;
336 this.setGlobalEventEnabled( 16r01 /* KeyPress */, true );
340 *globalKeyUpAction_ { arg action;
341 globalKeyUpAction = action;
342 this.setGlobalEventEnabled( 16r02 /* KeyRelease */, true );
345 keyDownAction_ { arg aFunction;
346 keyDownAction = aFunction;
347 this.setEventHandlerEnabled( QObject.keyDownEvent, true );
350 keyUpAction_ { arg aFunction;
351 keyUpAction = aFunction;
352 this.setEventHandlerEnabled( QObject.keyUpEvent, true );
355 keyModifiersChangedAction_ { arg aFunction;
356 keyModifiersChangedAction = aFunction;
357 this.setEventHandlerEnabled( QObject.keyDownEvent, true );
358 this.setEventHandlerEnabled( QObject.keyUpEvent, true );
361 mouseDownAction_ { arg aFunction;
362 mouseDownAction = aFunction;
363 this.setEventHandler( QObject.mouseDownEvent, \mouseDownEvent, true );
364 this.setEventHandler( QObject.mouseDblClickEvent, \mouseDownEvent, true );
367 mouseUpAction_ { arg aFunction;
368 mouseUpAction = aFunction;
369 this.setEventHandler( QObject.mouseUpEvent, \mouseUpEvent, true );
372 mouseMoveAction_ { arg aFunction;
373 mouseMoveAction = aFunction;
374 this.setEventHandler( QObject.mouseMoveEvent, \mouseMoveEvent, true );
377 mouseOverAction_ { arg aFunction;
378 mouseOverAction = aFunction;
379 this.setEventHandler( QObject.mouseOverEvent, \mouseOverEvent, true );
382 mouseLeaveAction_ { arg aFunction;
383 mouseLeaveAction = aFunction;
384 this.setEventHandler( QObject.mouseLeaveEvent, \mouseLeaveEvent, true );
387 mouseWheelAction_ { arg aFunction;
388 mouseWheelAction = aFunction;
389 this.setEventHandler( QObject.mouseWheelEvent, \mouseWheelEvent, true );
392 beginDragAction_ { arg handler;
393 beginDragAction = handler;
394 this.setEventHandler( QObject.mouseDownEvent, \mouseDownEvent, true )
397 canReceiveDragHandler_ { arg handler;
398 canReceiveDragHandler = handler;
399 this.setDragEventsEnabled( true );
402 receiveDragHandler_ { arg handler;
403 receiveDragHandler = handler;
404 this.setDragEventsEnabled( true );
407 toFrontAction_ { arg aFunction;
408 toFrontAction = aFunction;
409 this.setEventHandler( QObject.windowActivateEvent,
410 \onWindowActivateEvent );
413 endFrontAction_ { arg aFunction;
414 endFrontAction = aFunction;
415 this.setEventHandler( QObject.windowDeactivateEvent,
416 \onWindowDeactivateEvent );
419 focusGainedAction_ { arg handler;
420 focusGainedAction = handler;
421 this.setEventHandler( 8 /* QEvent::FocusIn */, \focusInEvent );
424 focusLostAction_ { arg handler;
425 focusLostAction = handler;
426 this.setEventHandler( 9 /* QEvent::FocusOut */, \focusOutEvent );
430 this.manageFunctionConnection( onClose, func, 'destroyed()', false );
438 defaultKeyDownAction { arg char, modifiers, unicode, keycode; }
440 defaultKeyUpAction { arg char, modifiers, unicode, keycode; }
442 keyDown { arg char, modifiers, unicode, keycode;
443 if( keyDownAction.notNil ) {
444 ^keyDownAction.value( this, char, modifiers, unicode, keycode );
446 ^this.defaultKeyDownAction( char, modifiers, unicode, keycode );
450 keyUp { arg char, modifiers, unicode, keycode;
452 if( keyUpAction.notNil ) {
453 ^keyUpAction.value( this, char, modifiers, unicode, keycode );
455 ^this.defaultKeyUpAction( char, modifiers, unicode, keycode );
459 keyModifiersChanged { arg modifiers;
460 keyModifiersChangedAction.value( this, modifiers);
463 mouseDown { arg x, y, modifiers, buttonNumber, clickCount;
464 ^mouseDownAction.value( this, x, y, modifiers, buttonNumber, clickCount );
467 mouseUp { arg x, y, modifiers, buttonNumber;
468 ^mouseUpAction.value( this, x, y, modifiers, buttonNumber );
471 mouseMove { arg x, y, modifiers;
472 ^mouseMoveAction.value( this, x, y, modifiers );
475 mouseOver { arg x, y;
476 ^mouseOverAction.value( this, x, y );
479 mouseLeave { arg x, y;
480 ^mouseLeaveAction.value( this, x, y );
483 mouseWheel { arg x, y, modifiers, xDelta, yDelta;
484 ^mouseWheelAction.value( this, x, y, modifiers, xDelta, yDelta );
487 /* ---------------- private ----------------------- */
489 *prSetCurrentDrag { arg obj; currentDrag = obj; currentDragString = obj.asCompileString; }
490 *prClearCurrentDrag { currentDrag = nil; currentDragString = nil; }
492 *setGlobalEventEnabled { arg event, enabled;
493 _QWidget_SetGlobalEventEnabled
496 initQView { arg parent;
498 var handleKeyDown, handleKeyUp, overridesMouseDown, handleDrag;
501 if( parent.decorator.notNil ) { parent.decorator.place(this) }
504 this.setEventHandler( QObject.closeEvent, \onCloseEvent, true );
507 handleKeyDown = handleKeyUp = this.overrides( \keyModifiersChanged );
508 if( handleKeyDown.not )
509 { handleKeyDown = this.overrides( \defaultKeyDownAction ) };
510 if( handleKeyUp.not )
511 { handleKeyUp = this.overrides( \defaultKeyUpAction )};
513 this.setEventHandler( QObject.keyDownEvent, \keyDownEvent, true, enabled: handleKeyDown );
514 this.setEventHandler( QObject.keyUpEvent, \keyUpEvent, true, enabled: handleKeyUp );
517 overridesMouseDown = this.overrides( \mouseDown );
518 if( this.respondsTo(\defaultGetDrag) || overridesMouseDown )
519 {this.setEventHandler( QObject.mouseDownEvent, \mouseDownEvent, true )};
520 if( overridesMouseDown )
521 {this.setEventHandler( QObject.mouseDblClickEvent, \mouseDownEvent, true )};
522 if( this.overrides( \mouseUp ) )
523 {this.setEventHandler( QObject.mouseUpEvent, \mouseUpEvent, true )};
524 if( this.overrides( \mouseMove ) )
525 {this.setEventHandler( QObject.mouseMoveEvent, \mouseMoveEvent, true )};
526 if( this.overrides( \mouseOver ) )
527 {this.setEventHandler( QObject.mouseOverEvent, \mouseOverEvent, true )};
528 if( this.overrides( \mouseLeave ) )
529 {this.setEventHandler( QObject.mouseLeaveEvent, \mouseLeaveEvent, true )};
530 if( this.overrides( \mouseWheel ) )
531 {this.setEventHandler( QObject.wheelEvent, \mouseWheelEvent, true )};
534 handleDrag = this.respondsTo(\defaultCanReceiveDrag) or: {this.respondsTo(\defaultReceiveDrag)};
535 this.setEventHandler( 60, \dragEnterEvent, true, enabled:handleDrag );
536 this.setEventHandler( 61, \dragMoveEvent, true, enabled:handleDrag );
537 this.setEventHandler( 63, \dropEvent, true, enabled:handleDrag );
541 if( userCanClose != false ) {
542 if( deleteOnClose != false ) { this.remove; ^true };
548 onWindowActivateEvent {
549 toFrontAction.value(this);
552 onWindowDeactivateEvent {
553 endFrontAction.value(this);
556 focusInEvent { focusGainedAction.value(this) }
557 focusOutEvent { focusLostAction.value(this) }
559 keyDownEvent { arg char, modifiers, unicode, keycode, spontaneous;
560 modifiers = QKeyModifiers.toCocoa(modifiers);
562 if( char.size > 0 ) {char = char[0]} {char = 0.asAscii};
565 // this event has never been propagated to parent yet
566 QView.globalKeyDownAction.value( this, char, modifiers, unicode, keycode );
569 if( (keycode == 16r1000020) || (keycode == 16r1000021) ||
570 (keycode == 16r1000022) || (keycode == 16r1000023 ) )
571 { this.keyModifiersChanged( modifiers ) };
573 ^this.keyDown( char, modifiers, unicode, keycode );
576 keyUpEvent { arg char, modifiers, unicode, keycode, spontaneous;
577 modifiers = QKeyModifiers.toCocoa(modifiers);
579 if( char.size > 0 ) {char = char[0]} {char = 0.asAscii};
582 // this event has never been propagated to parent yet
583 QView.globalKeyUpAction.value( this, char, modifiers, unicode, keycode );
586 if( (keycode == 16r1000020) || (keycode == 16r1000021) ||
587 (keycode == 16r1000022) || (keycode == 16r1000023 ) )
588 { this.keyModifiersChanged( modifiers ) };
590 ^this.keyUp( char, modifiers, unicode, keycode );
593 mouseDownEvent { arg x, y, modifiers, buttonNumber, clickCount;
594 // WARNING: QDragView and QListView override this method!
596 if( (modifiers & QKeyModifiers.control) > 0 ) { // if Ctrl / Cmd mod
597 // Try to get drag obj and start a drag.
598 // If successful, block further processing of this event.
599 if( this.beginDrag( x, y ) ) { ^false };
602 // else continue to handle mouse down event
603 modifiers = QKeyModifiers.toCocoa(modifiers);
604 ^this.mouseDown( x, y, modifiers, buttonNumber, clickCount );
607 mouseUpEvent { arg x, y, modifiers, buttonNumber;
608 modifiers = QKeyModifiers.toCocoa(modifiers);
609 ^this.mouseUp( x, y, modifiers, buttonNumber );
612 mouseMoveEvent { arg x, y, modifiers;
613 modifiers = QKeyModifiers.toCocoa(modifiers);
614 ^this.mouseMove( x, y, modifiers );
617 mouseOverEvent { arg x, y;
618 var dummy = x; // prevent this method from being optimized away
619 ^this.mouseOver( x, y );
622 mouseLeaveEvent { arg x, y;
623 var dummy = x; // prevent this method from being optimized away
624 ^this.mouseLeave( x, y );
627 mouseWheelEvent { arg x, y, modifiers, xDelta, yDelta;
628 modifiers = QKeyModifiers.toCocoa(modifiers);
629 ^this.mouseWheel( x, y, modifiers, xDelta, yDelta );
632 beginDrag { arg x, y;
634 if( beginDragAction.notNil )
635 { obj = beginDragAction.value( this, x, y ) }
636 { obj = this.tryPerform( \defaultGetDrag, x, y ) };
638 QView.prSetCurrentDrag( obj );
640 this.prStartDrag( dragLabel ?? str, obj, str );
646 canReceiveDrag { arg x, y;
647 if( canReceiveDragHandler.notNil )
648 { ^this.canReceiveDragHandler.value( this, x, y ) }
649 { ^( this.tryPerform( \defaultCanReceiveDrag, x, y ) ? false ) };
652 receiveDrag { arg x, y;
653 if( receiveDragHandler.notNil )
654 { this.receiveDragHandler.value( this, x, y ) }
655 { this.tryPerform( \defaultReceiveDrag, x, y ) };
658 prStartDrag { arg label, data, dataAsString;
660 ^this.primitiveFailed;
664 // always accept the event
668 dragMoveEvent { arg x, y;
669 // make sure the event is always consumed
670 ^this.canReceiveDrag( x, y ).switch (
677 dropEvent { arg x, y;
678 this.receiveDrag( x, y );
679 // always accept the event
683 setDragEventsEnabled { arg enabled;
684 this.setEventHandlerEnabled( 60, enabled );
685 this.setEventHandlerEnabled( 61, enabled );
686 this.setEventHandlerEnabled( 63, enabled );
689 prSetLayout { arg layout;
691 ^this.primitiveFailed;
694 manageMethodConnection { arg oldAction, newAction, signal, method, sync=false;
695 if( newAction !== oldAction ) {
697 { oldAction.isNil && newAction.notNil } {this.connectMethod (signal, method, sync)}
698 { oldAction.notNil && newAction.isNil } {this.disconnectMethod (signal, method)}
703 manageFunctionConnection { arg oldAction, newAction, signal, sync=false;
704 if( newAction !== oldAction ) {
705 if( oldAction.notNil ) {this.disconnectFunction (signal, oldAction)};
706 if( newAction.notNil ) {this.connectFunction (signal, newAction, sync)};
710 overrides { arg symMethod;
711 ^ ( this.class.findRespondingMethodFor(symMethod) !=
712 QView.findRespondingMethodFor(symMethod) );
715 nonimpl { arg methodName;
716 this.class.nonimpl( methodName );
719 *nonimpl { arg methodName;
720 this.debug( msg: methodName.asString ++ " is not implemented yet" )
723 *debug { arg level = 1, msg = "";
724 if( QtGUI.debugLevel >= level ) { ("Qt: " ++ this.asString ++ ": " ++ msg).postln }