1234567891011121314151617181920212223242526272829303132333435363738394041424344 |
- export default class GlassPane{constructor(){this._widget=new UI.Widget(true);this._widget.markAsRoot();this.element=this._widget.element;this.contentElement=this._widget.contentElement;this._arrowElement=UI.Icon.create('','arrow hidden');this.element.shadowRoot.appendChild(this._arrowElement);this.registerRequiredCSS('ui/glassPane.css');this.setPointerEventsBehavior(GlassPane.PointerEventsBehavior.PierceGlassPane);this._onMouseDownBound=this._onMouseDown.bind(this);this._onClickOutsideCallback=null;this._maxSize=null;this._positionX=null;this._positionY=null;this._anchorBox=null;this._anchorBehavior=GlassPane.AnchorBehavior.PreferTop;this._sizeBehavior=GlassPane.SizeBehavior.SetExactSize;this._marginBehavior=GlassPane.MarginBehavior.DefaultMargin;}
- isShowing(){return this._widget.isShowing();}
- registerRequiredCSS(cssFile){this._widget.registerRequiredCSS(cssFile);}
- setDefaultFocusedElement(element){this._widget.setDefaultFocusedElement(element);}
- setDimmed(dimmed){this.element.classList.toggle('dimmed-pane',dimmed);}
- setPointerEventsBehavior(pointerEventsBehavior){this.element.classList.toggle('no-pointer-events',pointerEventsBehavior!==GlassPane.PointerEventsBehavior.BlockedByGlassPane);this.contentElement.classList.toggle('no-pointer-events',pointerEventsBehavior===GlassPane.PointerEventsBehavior.PierceContents);}
- setOutsideClickCallback(callback){this._onClickOutsideCallback=callback;}
- setMaxContentSize(size){this._maxSize=size;this._positionContent();}
- setSizeBehavior(sizeBehavior){this._sizeBehavior=sizeBehavior;this._positionContent();}
- setContentPosition(x,y){this._positionX=x;this._positionY=y;this._positionContent();}
- setContentAnchorBox(anchorBox){this._anchorBox=anchorBox;this._positionContent();}
- setAnchorBehavior(behavior){this._anchorBehavior=behavior;}
- setMarginBehavior(behavior){this._marginBehavior=behavior;this._arrowElement.classList.toggle('hidden',behavior!==GlassPane.MarginBehavior.Arrow);}
- show(document){if(this.isShowing()){return;}
- this.element.style.zIndex=3000+1000*_panes.size;document.body.addEventListener('mousedown',this._onMouseDownBound,true);this._widget.show(document.body);_panes.add(this);this._positionContent();}
- hide(){if(!this.isShowing()){return;}
- _panes.delete(this);this.element.ownerDocument.body.removeEventListener('mousedown',this._onMouseDownBound,true);this._widget.detach();}
- _onMouseDown(event){if(!this._onClickOutsideCallback){return;}
- const node=event.deepElementFromPoint();if(!node||this.contentElement.isSelfOrAncestor(node)){return;}
- this._onClickOutsideCallback.call(null,event);}
- _positionContent(){if(!this.isShowing()){return;}
- const showArrow=this._marginBehavior===GlassPane.MarginBehavior.Arrow;const gutterSize=showArrow?8:(this._marginBehavior===GlassPane.MarginBehavior.NoMargin?0:3);const scrollbarSize=UI.measuredScrollbarWidth(this.element.ownerDocument);const arrowSize=10;const container=_containers.get((this.element.ownerDocument));if(this._sizeBehavior===GlassPane.SizeBehavior.MeasureContent){this.contentElement.positionAt(0,0);this.contentElement.style.width='';this.contentElement.style.maxWidth='';this.contentElement.style.height='';this.contentElement.style.maxHeight='';}
- const containerWidth=container.offsetWidth;const containerHeight=container.offsetHeight;let width=containerWidth-gutterSize*2;let height=containerHeight-gutterSize*2;let positionX=gutterSize;let positionY=gutterSize;if(this._maxSize){width=Math.min(width,this._maxSize.width);height=Math.min(height,this._maxSize.height);}
- if(this._sizeBehavior===GlassPane.SizeBehavior.MeasureContent){const measuredRect=this.contentElement.getBoundingClientRect();const widthOverflow=height<measuredRect.height?scrollbarSize:0;const heightOverflow=width<measuredRect.width?scrollbarSize:0;width=Math.min(width,measuredRect.width+widthOverflow);height=Math.min(height,measuredRect.height+heightOverflow);}
- if(this._anchorBox){const anchorBox=this._anchorBox.relativeToElement(container);let behavior=this._anchorBehavior;this._arrowElement.classList.remove('arrow-none','arrow-top','arrow-bottom','arrow-left','arrow-right');if(behavior===GlassPane.AnchorBehavior.PreferTop||behavior===GlassPane.AnchorBehavior.PreferBottom){const top=anchorBox.y-2*gutterSize;const bottom=containerHeight-anchorBox.y-anchorBox.height-2*gutterSize;if(behavior===GlassPane.AnchorBehavior.PreferTop&&top<height&&bottom>top){behavior=GlassPane.AnchorBehavior.PreferBottom;}
- if(behavior===GlassPane.AnchorBehavior.PreferBottom&&bottom<height&&top>bottom){behavior=GlassPane.AnchorBehavior.PreferTop;}
- let arrowY;let enoughHeight=true;if(behavior===GlassPane.AnchorBehavior.PreferTop){positionY=Math.max(gutterSize,anchorBox.y-height-gutterSize);const spaceTop=anchorBox.y-positionY-gutterSize;if(this._sizeBehavior===GlassPane.SizeBehavior.MeasureContent){if(height>spaceTop){this._arrowElement.classList.add('arrow-none');enoughHeight=false;}}else{height=Math.min(height,spaceTop);}
- this._arrowElement.setIconType('mediumicon-arrow-bottom');this._arrowElement.classList.add('arrow-bottom');arrowY=anchorBox.y-gutterSize;}else{positionY=anchorBox.y+anchorBox.height+gutterSize;const spaceBottom=containerHeight-positionY-gutterSize;if(this._sizeBehavior===GlassPane.SizeBehavior.MeasureContent){if(height>spaceBottom){this._arrowElement.classList.add('arrow-none');positionY=containerHeight-gutterSize-height;enoughHeight=false;}}else{height=Math.min(height,spaceBottom);}
- this._arrowElement.setIconType('mediumicon-arrow-top');this._arrowElement.classList.add('arrow-top');arrowY=anchorBox.y+anchorBox.height+gutterSize;}
- positionX=Math.max(gutterSize,Math.min(anchorBox.x,containerWidth-width-gutterSize));if(!enoughHeight){positionX=Math.min(positionX+arrowSize,containerWidth-width-gutterSize);}else if(showArrow&&positionX-arrowSize>=gutterSize){positionX-=arrowSize;}
- width=Math.min(width,containerWidth-positionX-gutterSize);if(2*arrowSize>=width){this._arrowElement.classList.add('arrow-none');}else{let arrowX=anchorBox.x+Math.min(50,Math.floor(anchorBox.width/2));arrowX=Number.constrain(arrowX,positionX+arrowSize,positionX+width-arrowSize);this._arrowElement.positionAt(arrowX,arrowY,container);}}else{const left=anchorBox.x-2*gutterSize;const right=containerWidth-anchorBox.x-anchorBox.width-2*gutterSize;if(behavior===GlassPane.AnchorBehavior.PreferLeft&&left<width&&right>left){behavior=GlassPane.AnchorBehavior.PreferRight;}
- if(behavior===GlassPane.AnchorBehavior.PreferRight&&right<width&&left>right){behavior=GlassPane.AnchorBehavior.PreferLeft;}
- let arrowX;let enoughWidth=true;if(behavior===GlassPane.AnchorBehavior.PreferLeft){positionX=Math.max(gutterSize,anchorBox.x-width-gutterSize);const spaceLeft=anchorBox.x-positionX-gutterSize;if(this._sizeBehavior===GlassPane.SizeBehavior.MeasureContent){if(width>spaceLeft){this._arrowElement.classList.add('arrow-none');enoughWidth=false;}}else{width=Math.min(width,spaceLeft);}
- this._arrowElement.setIconType('mediumicon-arrow-right');this._arrowElement.classList.add('arrow-right');arrowX=anchorBox.x-gutterSize;}else{positionX=anchorBox.x+anchorBox.width+gutterSize;const spaceRight=containerWidth-positionX-gutterSize;if(this._sizeBehavior===GlassPane.SizeBehavior.MeasureContent){if(width>spaceRight){this._arrowElement.classList.add('arrow-none');positionX=containerWidth-gutterSize-width;enoughWidth=false;}}else{width=Math.min(width,spaceRight);}
- this._arrowElement.setIconType('mediumicon-arrow-left');this._arrowElement.classList.add('arrow-left');arrowX=anchorBox.x+anchorBox.width+gutterSize;}
- positionY=Math.max(gutterSize,Math.min(anchorBox.y,containerHeight-height-gutterSize));if(!enoughWidth){positionY=Math.min(positionY+arrowSize,containerHeight-height-gutterSize);}else if(showArrow&&positionY-arrowSize>=gutterSize){positionY-=arrowSize;}
- height=Math.min(height,containerHeight-positionY-gutterSize);if(2*arrowSize>=height){this._arrowElement.classList.add('arrow-none');}else{let arrowY=anchorBox.y+Math.min(50,Math.floor(anchorBox.height/2));arrowY=Number.constrain(arrowY,positionY+arrowSize,positionY+height-arrowSize);this._arrowElement.positionAt(arrowX,arrowY,container);}}}else{positionX=this._positionX!==null?this._positionX:(containerWidth-width)/2;positionY=this._positionY!==null?this._positionY:(containerHeight-height)/2;width=Math.min(width,containerWidth-positionX-gutterSize);height=Math.min(height,containerHeight-positionY-gutterSize);this._arrowElement.classList.add('arrow-none');}
- this.contentElement.style.width=width+'px';if(this._sizeBehavior===GlassPane.SizeBehavior.SetExactWidthMaxHeight){this.contentElement.style.maxHeight=height+'px';}else{this.contentElement.style.height=height+'px';}
- this.contentElement.positionAt(positionX,positionY,container);this._widget.doResize();}
- widget(){return this._widget;}
- static setContainer(element){_containers.set((element.ownerDocument),element);GlassPane.containerMoved(element);}
- static container(document){return _containers.get(document);}
- static containerMoved(element){for(const pane of _panes){if(pane.isShowing()&&pane.element.ownerDocument===element.ownerDocument){pane._positionContent();}}}}
- export const PointerEventsBehavior={BlockedByGlassPane:Symbol('BlockedByGlassPane'),PierceGlassPane:Symbol('PierceGlassPane'),PierceContents:Symbol('PierceContents')};export const AnchorBehavior={PreferTop:Symbol('PreferTop'),PreferBottom:Symbol('PreferBottom'),PreferLeft:Symbol('PreferLeft'),PreferRight:Symbol('PreferRight'),};export const SizeBehavior={SetExactSize:Symbol('SetExactSize'),SetExactWidthMaxHeight:Symbol('SetExactWidthMaxHeight'),MeasureContent:Symbol('MeasureContent')};export const MarginBehavior={Arrow:Symbol('Arrow'),DefaultMargin:Symbol('DefaultMargin'),NoMargin:Symbol('NoMargin')};const _containers=new Map();const _panes=new Set();self.UI=self.UI||{};UI=UI||{};UI.GlassPane=GlassPane;UI.GlassPane.PointerEventsBehavior=PointerEventsBehavior;UI.GlassPane.AnchorBehavior=AnchorBehavior;UI.GlassPane.SizeBehavior=SizeBehavior;UI.GlassPane.MarginBehavior=MarginBehavior;UI.GlassPane._panes=_panes;
|