@@ -19,7 +19,7 @@ import { isString } from '../../../base/common/types.js';
19
19
import { localize } from '../../../nls.js' ;
20
20
import { IInputBox , IInputOptions , IKeyMods , IPickOptions , IQuickInput , IQuickInputButton , IQuickNavigateConfiguration , IQuickPick , IQuickPickItem , IQuickWidget , QuickInputHideReason , QuickPickInput , QuickPickFocus } from '../common/quickInput.js' ;
21
21
import { QuickInputBox } from './quickInputBox.js' ;
22
- import { QuickInputUI , Writeable , IQuickInputStyles , IQuickInputOptions , QuickPick , backButton , InputBox , Visibilities , QuickWidget , InQuickInputContextKey , QuickInputTypeContextKey , EndOfQuickInputBoxContextKey } from './quickInput.js' ;
22
+ import { QuickInputUI , Writeable , IQuickInputStyles , IQuickInputOptions , QuickPick , backButton , InputBox , Visibilities , QuickWidget , InQuickInputContextKey , QuickInputTypeContextKey , EndOfQuickInputBoxContextKey , QuickInputAlignmentContextKey } from './quickInput.js' ;
23
23
import { ILayoutService } from '../../layout/browser/layoutService.js' ;
24
24
import { mainWindow } from '../../../base/browser/window.js' ;
25
25
import { IInstantiationService } from '../../instantiation/common/instantiation.js' ;
@@ -331,7 +331,20 @@ export class QuickInputController extends Disposable {
331
331
332
332
// Drag and Drop support
333
333
this . dndController = this . _register ( this . instantiationService . createInstance (
334
- QuickInputDragAndDropController , this . _container , container , [ titleBar , title , headerContainer ] ) ) ;
334
+ QuickInputDragAndDropController ,
335
+ this . _container ,
336
+ container ,
337
+ [
338
+ {
339
+ node : titleBar ,
340
+ includeChildren : true
341
+ } ,
342
+ {
343
+ node : headerContainer ,
344
+ includeChildren : false
345
+ }
346
+ ]
347
+ ) ) ;
335
348
336
349
// DnD update layout
337
350
this . _register ( autorun ( reader => {
@@ -607,6 +620,10 @@ export class QuickInputController extends Disposable {
607
620
return new InputBox ( ui ) ;
608
621
}
609
622
623
+ setAlignment ( alignment : 'top' | 'center' | { top : number ; left : number } ) : void {
624
+ this . dndController ?. setAlignment ( alignment ) ;
625
+ }
626
+
610
627
createQuickWidget ( ) : IQuickWidget {
611
628
const ui = this . getUI ( true ) ;
612
629
return new QuickWidget ( ui ) ;
@@ -879,16 +896,19 @@ class QuickInputDragAndDropController extends Disposable {
879
896
readonly dndViewState = observableValue < { top ?: number ; left ?: number ; done : boolean } | undefined > ( this , undefined ) ;
880
897
881
898
private readonly _snapThreshold = 20 ;
882
- private readonly _snapLineHorizontalRatio = 0.15 ;
899
+ private readonly _snapLineHorizontalRatio = 0.25 ;
883
900
private readonly _snapLineHorizontal : HTMLElement ;
884
901
private readonly _snapLineVertical1 : HTMLElement ;
885
902
private readonly _snapLineVertical2 : HTMLElement ;
886
903
904
+ private _quickInputAlignmentContext = QuickInputAlignmentContextKey . bindTo ( this . _contextKeyService ) ;
905
+
887
906
constructor (
888
907
private _container : HTMLElement ,
889
908
private readonly _quickInputContainer : HTMLElement ,
890
- private _quickInputDragAreas : HTMLElement [ ] ,
891
- @ILayoutService private readonly _layoutService : ILayoutService
909
+ private _quickInputDragAreas : { node : HTMLElement ; includeChildren : boolean } [ ] ,
910
+ @ILayoutService private readonly _layoutService : ILayoutService ,
911
+ @IContextKeyService private readonly _contextKeyService : IContextKeyService
892
912
) {
893
913
super ( ) ;
894
914
@@ -909,87 +929,138 @@ class QuickInputDragAndDropController extends Disposable {
909
929
dom . append ( this . _container , this . _snapLineVertical2 ) ;
910
930
}
911
931
932
+ setAlignment ( alignment : 'top' | 'center' | { top : number ; left : number } , done = true ) : void {
933
+ if ( alignment === 'top' ) {
934
+ this . dndViewState . set ( {
935
+ top : this . _getTopSnapValue ( ) / this . _container . clientHeight ,
936
+ left : ( this . _getCenterXSnapValue ( ) + ( this . _quickInputContainer . clientWidth / 2 ) ) / this . _container . clientWidth ,
937
+ done
938
+ } , undefined ) ;
939
+ this . _quickInputAlignmentContext . set ( 'top' ) ;
940
+ } else if ( alignment === 'center' ) {
941
+ this . dndViewState . set ( {
942
+ top : this . _getCenterYSnapValue ( ) / this . _container . clientHeight ,
943
+ left : ( this . _getCenterXSnapValue ( ) + ( this . _quickInputContainer . clientWidth / 2 ) ) / this . _container . clientWidth ,
944
+ done
945
+ } , undefined ) ;
946
+ this . _quickInputAlignmentContext . set ( 'center' ) ;
947
+ } else {
948
+ this . dndViewState . set ( { top : alignment . top , left : alignment . left , done } , undefined ) ;
949
+ this . _quickInputAlignmentContext . set ( undefined ) ;
950
+ }
951
+ }
952
+
912
953
private registerMouseListeners ( ) : void {
913
- for ( const dragArea of this . _quickInputDragAreas ) {
914
- let top : number | undefined ;
915
- let left : number | undefined ;
954
+ let top : number | undefined ;
955
+ let left : number | undefined ;
956
+ const dragArea = this . _quickInputContainer ;
957
+
958
+ // Double click
959
+ this . _register ( dom . addDisposableGenericMouseUpListener ( dragArea , ( event : MouseEvent ) => {
960
+ const originEvent = new StandardMouseEvent ( dom . getWindow ( dragArea ) , event ) ;
961
+ if ( originEvent . detail !== 2 ) {
962
+ return ;
963
+ }
916
964
917
- // Double click
918
- this . _register ( dom . addDisposableGenericMouseUpListener ( dragArea , ( event : MouseEvent ) => {
919
- const originEvent = new StandardMouseEvent ( dom . getWindow ( dragArea ) , event ) ;
965
+ // Ignore event if the target is not the drag area
966
+ if ( ! this . _quickInputDragAreas . some ( ( { node, includeChildren } ) => includeChildren ? dom . isAncestor ( originEvent . target as HTMLElement , node ) : originEvent . target === node ) ) {
967
+ return ;
968
+ }
920
969
921
- // Ignore event if the target is not the drag area
922
- if ( originEvent . target !== dragArea ) {
923
- return ;
924
- }
970
+ top = undefined ;
971
+ left = undefined ;
925
972
926
- if ( originEvent . detail === 2 ) {
927
- top = undefined ;
928
- left = undefined ;
973
+ this . dndViewState . set ( { top, left, done : true } , undefined ) ;
974
+ } ) ) ;
929
975
930
- this . dndViewState . set ( { top, left, done : true } , undefined ) ;
931
- }
932
- } ) ) ;
976
+ // Mouse down
977
+ this . _register ( dom . addDisposableGenericMouseDownListener ( dragArea , ( e : MouseEvent ) => {
978
+ const activeWindow = dom . getWindow ( this . _layoutService . activeContainer ) ;
979
+ const originEvent = new StandardMouseEvent ( activeWindow , e ) ;
933
980
934
- // Mouse down
935
- this . _register ( dom . addDisposableGenericMouseDownListener ( dragArea , ( e : MouseEvent ) => {
936
- const activeWindow = dom . getWindow ( this . _layoutService . activeContainer ) ;
937
- const originEvent = new StandardMouseEvent ( activeWindow , e ) ;
981
+ // Ignore event if the target is not the drag area
982
+ if ( ! this . _quickInputDragAreas . some ( ( { node , includeChildren } ) => includeChildren ? dom . isAncestor ( originEvent . target as HTMLElement , node ) : originEvent . target === node ) ) {
983
+ return ;
984
+ }
938
985
939
- // Ignore event if the target is not the drag area
940
- if ( originEvent . target !== dragArea ) {
941
- return ;
986
+ // Mouse position offset relative to dragArea
987
+ const dragAreaRect = this . _quickInputContainer . getBoundingClientRect ( ) ;
988
+ const dragOffsetX = originEvent . browserEvent . clientX - dragAreaRect . left ;
989
+ const dragOffsetY = originEvent . browserEvent . clientY - dragAreaRect . top ;
990
+
991
+ // Snap lines
992
+ let isMovingQuickInput = false ;
993
+ const snapCoordinateYTop = this . _getTopSnapValue ( ) ;
994
+ const snapCoordinateY = this . _getCenterYSnapValue ( ) ;
995
+ const snapCoordinateX = this . _getCenterXSnapValue ( ) ;
996
+
997
+ // Mouse move
998
+ const mouseMoveListener = dom . addDisposableGenericMouseMoveListener ( activeWindow , ( e : MouseEvent ) => {
999
+ const mouseMoveEvent = new StandardMouseEvent ( activeWindow , e ) ;
1000
+ mouseMoveEvent . preventDefault ( ) ;
1001
+
1002
+ if ( ! isMovingQuickInput ) {
1003
+ this . _showSnapLines ( snapCoordinateY , snapCoordinateX ) ;
1004
+ isMovingQuickInput = true ;
942
1005
}
943
1006
944
- // Mouse position offset relative to dragArea
945
- const dragAreaRect = this . _quickInputContainer . getBoundingClientRect ( ) ;
946
- const dragOffsetX = originEvent . browserEvent . clientX - dragAreaRect . left ;
947
- const dragOffsetY = originEvent . browserEvent . clientY - dragAreaRect . top ;
948
-
949
- // Snap lines
950
- let snapLinesVisible = false ;
951
- const snapCoordinateYTop = this . _layoutService . activeContainerOffset . quickPickTop ;
952
- const snapCoordinateY = Math . round ( this . _container . clientHeight * this . _snapLineHorizontalRatio ) ;
953
- const snapCoordinateX = Math . round ( this . _container . clientWidth / 2 ) - Math . round ( this . _quickInputContainer . clientWidth / 2 ) ;
954
-
955
- // Mouse move
956
- const mouseMoveListener = dom . addDisposableGenericMouseMoveListener ( activeWindow , ( e : MouseEvent ) => {
957
- const mouseMoveEvent = new StandardMouseEvent ( activeWindow , e ) ;
958
- mouseMoveEvent . preventDefault ( ) ;
959
-
960
- if ( ! snapLinesVisible ) {
961
- this . _showSnapLines ( snapCoordinateY , snapCoordinateX ) ;
962
- snapLinesVisible = true ;
1007
+ let topCoordinate = e . clientY - dragOffsetY ;
1008
+ // Make sure the quick input is not moved outside the container
1009
+ topCoordinate = Math . max ( 0 , Math . min ( topCoordinate , this . _container . clientHeight - this . _quickInputContainer . clientHeight ) ) ;
1010
+ const snappingToTop = Math . abs ( topCoordinate - snapCoordinateYTop ) < this . _snapThreshold ;
1011
+ topCoordinate = snappingToTop ? snapCoordinateYTop : topCoordinate ;
1012
+ const snappingToCenter = Math . abs ( topCoordinate - snapCoordinateY ) < this . _snapThreshold ;
1013
+ topCoordinate = snappingToCenter ? snapCoordinateY : topCoordinate ;
1014
+ top = topCoordinate / this . _container . clientHeight ;
1015
+
1016
+ let leftCoordinate = e . clientX - dragOffsetX ;
1017
+ // Make sure the quick input is not moved outside the container
1018
+ leftCoordinate = Math . max ( 0 , Math . min ( leftCoordinate , this . _container . clientWidth - this . _quickInputContainer . clientWidth ) ) ;
1019
+ const snappingToCenterX = Math . abs ( leftCoordinate - snapCoordinateX ) < this . _snapThreshold ;
1020
+ leftCoordinate = snappingToCenterX ? snapCoordinateX : leftCoordinate ;
1021
+ left = ( leftCoordinate + ( this . _quickInputContainer . clientWidth / 2 ) ) / this . _container . clientWidth ;
1022
+
1023
+ this . dndViewState . set ( { top, left, done : false } , undefined ) ;
1024
+ if ( snappingToCenterX ) {
1025
+ if ( snappingToTop ) {
1026
+ this . _quickInputAlignmentContext . set ( 'top' ) ;
1027
+ return ;
1028
+ } else if ( snappingToCenter ) {
1029
+ this . _quickInputAlignmentContext . set ( 'center' ) ;
1030
+ return ;
963
1031
}
1032
+ }
1033
+ this . _quickInputAlignmentContext . set ( undefined ) ;
1034
+ } ) ;
964
1035
965
- let topCoordinate = e . clientY - dragOffsetY ;
966
- topCoordinate = Math . max ( 0 , Math . min ( topCoordinate , this . _container . clientHeight - this . _quickInputContainer . clientHeight ) ) ;
967
- topCoordinate = Math . abs ( topCoordinate - snapCoordinateYTop ) < this . _snapThreshold ? snapCoordinateYTop : topCoordinate ;
968
- topCoordinate = Math . abs ( topCoordinate - snapCoordinateY ) < this . _snapThreshold ? snapCoordinateY : topCoordinate ;
969
- top = topCoordinate / this . _container . clientHeight ;
970
-
971
- let leftCoordinate = e . clientX - dragOffsetX ;
972
- leftCoordinate = Math . max ( 0 , Math . min ( leftCoordinate , this . _container . clientWidth - this . _quickInputContainer . clientWidth ) ) ;
973
- leftCoordinate = Math . abs ( leftCoordinate - snapCoordinateX ) < this . _snapThreshold ? snapCoordinateX : leftCoordinate ;
974
- left = ( leftCoordinate + ( this . _quickInputContainer . clientWidth / 2 ) ) / this . _container . clientWidth ;
975
-
976
- this . dndViewState . set ( { top, left, done : false } , undefined ) ;
977
- } ) ;
978
-
979
- // Mouse up
980
- const mouseUpListener = dom . addDisposableGenericMouseUpListener ( activeWindow , ( e : MouseEvent ) => {
1036
+ // Mouse up
1037
+ const mouseUpListener = dom . addDisposableGenericMouseUpListener ( activeWindow , ( e : MouseEvent ) => {
1038
+ if ( isMovingQuickInput ) {
981
1039
// Hide snaplines
982
1040
this . _hideSnapLines ( ) ;
983
1041
984
1042
// Save position
985
- this . dndViewState . set ( { top, left, done : true } , undefined ) ;
1043
+ const state = this . dndViewState . get ( ) ;
1044
+ this . dndViewState . set ( { top : state ?. top , left : state ?. left , done : true } , undefined ) ;
1045
+ }
986
1046
987
- // Dispose listeners
988
- mouseMoveListener . dispose ( ) ;
989
- mouseUpListener . dispose ( ) ;
990
- } ) ;
991
- } ) ) ;
992
- }
1047
+ // Dispose listeners
1048
+ mouseMoveListener . dispose ( ) ;
1049
+ mouseUpListener . dispose ( ) ;
1050
+ } ) ;
1051
+ } ) ) ;
1052
+ }
1053
+
1054
+ private _getTopSnapValue ( ) {
1055
+ return this . _layoutService . activeContainerOffset . quickPickTop ;
1056
+ }
1057
+
1058
+ private _getCenterYSnapValue ( ) {
1059
+ return Math . round ( this . _container . clientHeight * this . _snapLineHorizontalRatio ) ;
1060
+ }
1061
+
1062
+ private _getCenterXSnapValue ( ) {
1063
+ return Math . round ( this . _container . clientWidth / 2 ) - Math . round ( this . _quickInputContainer . clientWidth / 2 ) ;
993
1064
}
994
1065
995
1066
private _showSnapLines ( horizontal : number , vertical : number ) {
0 commit comments