@@ -4,6 +4,8 @@ import { CodeCell, MarkdownCell } from '@jupyterlab/cells';
44
55import { Widget } from '@lumino/widgets' ;
66
7+ import { MessageLoop } from '@lumino/messaging' ;
8+
79import { UUID , MimeData } from '@lumino/coreutils' ;
810
911import { ArrayExt } from '@lumino/algorithm' ;
@@ -23,8 +25,6 @@ import {
2325
2426import { Signal , ISignal } from '@lumino/signaling' ;
2527
26- import { DashboardIcons } from './icons' ;
27-
2828import { Widgetstore , WidgetPosition } from './widgetstore' ;
2929
3030import { DashboardLayout } from './layout' ;
@@ -132,8 +132,20 @@ export class DashboardWidget extends Widget {
132132 this . node . style . opacity = '0' ;
133133
134134 container . classList . add ( DASHBOARD_WIDGET_CHILD_CLASS ) ;
135- container . appendChild ( clone . node ) ;
136- this . node . appendChild ( container ) ;
135+
136+ // Fake an attach in order to render LaTeX properly.
137+ // Note: This is not how you should use Lumino widgets.
138+ if ( this . parent ) {
139+ if ( this . parent ! . isAttached ) {
140+ MessageLoop . sendMessage ( clone , Widget . Msg . BeforeAttach ) ;
141+ container . appendChild ( clone . node ) ;
142+ this . node . appendChild ( container ) ;
143+ if ( this . parent ! . isAttached ) {
144+ MessageLoop . sendMessage ( clone , Widget . Msg . AfterAttach ) ;
145+ }
146+ }
147+ }
148+
137149 this . _content = clone ;
138150
139151 const done = ( ) : void => {
@@ -152,8 +164,14 @@ export class DashboardWidget extends Widget {
152164 } ) ;
153165 }
154166
155- const resizer = DashboardWidget . createResizer ( ) ;
156- this . node . appendChild ( resizer ) ;
167+ const resizerTopLeft = DashboardWidget . createResizer ( 'top-left' ) ;
168+ const resizerTopRight = DashboardWidget . createResizer ( 'top-right' ) ;
169+ const resizerBottomLeft = DashboardWidget . createResizer ( 'bottom-left' ) ;
170+ const resizerBottomRight = DashboardWidget . createResizer ( 'bottom-right' ) ;
171+ this . node . appendChild ( resizerTopLeft ) ;
172+ this . node . appendChild ( resizerTopRight ) ;
173+ this . node . appendChild ( resizerBottomLeft ) ;
174+ this . node . appendChild ( resizerBottomRight ) ;
157175
158176 this . addClass ( DASHBOARD_WIDGET_CLASS ) ;
159177 this . addClass ( EDITABLE_WIDGET_CLASS ) ;
@@ -294,9 +312,19 @@ export class DashboardWidget extends Widget {
294312
295313 // this.node.style.opacity = '0.6';
296314
315+ const elem = target as HTMLElement ;
297316 // Set mode to resize if the mousedown happened on a resizer.
298- if ( ( target as HTMLElement ) . classList . contains ( 'pr-Resizer' ) ) {
317+ if ( elem . classList . contains ( 'pr-Resizer' ) ) {
299318 this . _mouseMode = 'resize' ;
319+ if ( elem . classList . contains ( 'pr-ResizerTopRight' ) ) {
320+ this . _selectedResizer = 'top-right' ;
321+ } else if ( elem . classList . contains ( 'pr-ResizerTopLeft' ) ) {
322+ this . _selectedResizer = 'top-left' ;
323+ } else if ( elem . classList . contains ( 'pr-ResizerBottomLeft' ) ) {
324+ this . _selectedResizer = 'bottom-left' ;
325+ } else {
326+ this . _selectedResizer = 'bottom-right' ;
327+ }
300328 } else {
301329 this . _mouseMode = 'drag' ;
302330 }
@@ -305,12 +333,16 @@ export class DashboardWidget extends Widget {
305333
306334 const rect = this . node . getBoundingClientRect ( ) ;
307335
336+ const { width, height, top, left } = this . pos ;
337+
308338 this . _clickData = {
309339 pressX : event . clientX ,
310340 pressY : event . clientY ,
311341 cell,
312- pressWidth : parseInt ( this . node . style . width , 10 ) ,
313- pressHeight : parseInt ( this . node . style . height , 10 ) ,
342+ origWidth : width ,
343+ origHeight : height ,
344+ origLeft : left ,
345+ origTop : top ,
314346 target : this . node . cloneNode ( true ) as HTMLElement ,
315347 widgetX : rect . left ,
316348 widgetY : rect . top
@@ -352,16 +384,44 @@ export class DashboardWidget extends Widget {
352384 * Handle `mousemove` events when the widget mouseMode is `resize`.
353385 */
354386 private _resizeMouseMove ( event : MouseEvent ) : void {
355- const { pressX, pressY, pressWidth, pressHeight } = this . _clickData ;
387+ const {
388+ pressX,
389+ pressY,
390+ origWidth,
391+ origHeight,
392+ origLeft,
393+ origTop
394+ } = this . _clickData ;
356395
357396 const deltaX = event . clientX - pressX ;
358397 const deltaY = event . clientY - pressY ;
359398
360- const width = Math . max ( pressWidth + deltaX , DashboardWidget . MIN_WIDTH ) ;
361- const height = Math . max ( pressHeight + deltaY , DashboardWidget . MIN_HEIGHT ) ;
399+ let { width, height, top, left } = this . pos ;
400+
401+ switch ( this . _selectedResizer ) {
402+ case 'bottom-right' :
403+ width = Math . max ( origWidth + deltaX , DashboardWidget . MIN_WIDTH ) ;
404+ height = Math . max ( origHeight + deltaY , DashboardWidget . MIN_HEIGHT ) ;
405+ break ;
406+ case 'bottom-left' :
407+ width = Math . max ( origWidth - deltaX , DashboardWidget . MIN_WIDTH ) ;
408+ height = Math . max ( origHeight + deltaY , DashboardWidget . MIN_HEIGHT ) ;
409+ left = origLeft + deltaX ;
410+ break ;
411+ case 'top-right' :
412+ width = Math . max ( origWidth + deltaX , DashboardWidget . MIN_WIDTH ) ;
413+ height = Math . max ( origHeight - deltaY , DashboardWidget . MIN_HEIGHT ) ;
414+ top = origTop + deltaY ;
415+ break ;
416+ case 'top-left' :
417+ width = Math . max ( origWidth - deltaX , DashboardWidget . MIN_WIDTH ) ;
418+ height = Math . max ( origHeight - deltaY , DashboardWidget . MIN_HEIGHT ) ;
419+ top = origTop + deltaY ;
420+ left = origLeft + deltaX ;
421+ break ;
422+ }
362423
363- this . node . style . width = `${ width } px` ;
364- this . node . style . height = `${ height } px` ;
424+ this . pos = { width, height, top, left } ;
365425
366426 if ( this . mode === 'grid-edit' ) {
367427 ( this . parent . layout as DashboardLayout ) . drawDropZone ( this . pos , '#2b98f0' ) ;
@@ -375,10 +435,14 @@ export class DashboardWidget extends Widget {
375435 * Fit widget width/height to the width/height of the underlying content.
376436 */
377437 fitContent ( ) : void {
378- const element = this . _content . node ;
438+ const element = this . _content . node . firstChild as HTMLElement ;
379439 // Pixels are added to prevent weird wrapping issues. Kind of a hack.
380- this . node . style . width = `${ element . clientWidth + 3 } px` ;
381- this . node . style . height = `${ element . clientHeight + 2 } px` ;
440+ this . pos = {
441+ width : element . clientWidth + 3 ,
442+ height : element . clientHeight + 2 ,
443+ left : undefined ,
444+ top : undefined
445+ } ;
382446 }
383447
384448 /**
@@ -642,15 +706,18 @@ export class DashboardWidget extends Widget {
642706 private _clickData : {
643707 pressX : number ;
644708 pressY : number ;
645- pressWidth : number ;
646- pressHeight : number ;
709+ origWidth : number ;
710+ origHeight : number ;
711+ origLeft : number ;
712+ origTop : number ;
647713 target : HTMLElement ;
648714 cell : CodeCell | MarkdownCell ;
649715 widgetX : number ;
650716 widgetY : number ;
651717 } | null = null ;
652718 private _locked = false ;
653719 private _content : Widget ;
720+ private _selectedResizer : DashboardWidget . ResizerCorner ;
654721}
655722
656723/**
@@ -710,18 +777,39 @@ export namespace DashboardWidget {
710777 return `DashboardWidget-${ UUID . uuid4 ( ) } ` ;
711778 }
712779
780+ /**
781+ * A type for describing the corner for a widget resizer.
782+ */
783+ export type ResizerCorner =
784+ | 'top-left'
785+ | 'bottom-left'
786+ | 'top-right'
787+ | 'bottom-right' ;
788+
713789 /**
714790 * Create a resizer element for a dashboard widget.
715791 */
716- export function createResizer ( ) : HTMLElement {
792+ export function createResizer ( corner : ResizerCorner ) : HTMLElement {
717793 const resizer = document . createElement ( 'div' ) ;
718794 resizer . classList . add ( 'pr-Resizer' ) ;
719- DashboardIcons . resizer2 . element ( {
720- container : resizer ,
721- width : '15px' ,
722- height : '15px' ,
723- pointerEvents : 'none'
724- } ) ;
795+
796+ switch ( corner ) {
797+ case 'top-left' :
798+ resizer . classList . add ( 'pr-ResizerTopLeft' ) ;
799+ break ;
800+ case 'top-right' :
801+ resizer . classList . add ( 'pr-ResizerTopRight' ) ;
802+ break ;
803+ case 'bottom-left' :
804+ resizer . classList . add ( 'pr-ResizerBottomLeft' ) ;
805+ break ;
806+ case 'bottom-right' :
807+ resizer . classList . add ( 'pr-ResizerBottomRight' ) ;
808+ break ;
809+ default :
810+ resizer . classList . add ( 'pr-ResizerBottomRight' ) ;
811+ break ;
812+ }
725813
726814 return resizer ;
727815 }
0 commit comments