/* * WindowFrame.java * * Copyright (C) 2009-12 by RStudio, Inc. * * Unless you have received this program directly from RStudio pursuant * to the terms of a commercial license agreement with RStudio, then * this program is licensed to you under the terms of version 3 of the * GNU Affero General Public License. This program is distributed WITHOUT * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details. * */ package org.rstudio.core.client.theme; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Float; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.*; import com.google.inject.Inject; import java.util.HashMap; import org.rstudio.core.client.events.*; import org.rstudio.core.client.layout.RequiresVisibilityChanged; import org.rstudio.core.client.layout.WindowState; import org.rstudio.core.client.theme.res.ThemeResources; import org.rstudio.core.client.theme.res.ThemeStyles; import org.rstudio.core.client.widget.BeforeShowCallback; import org.rstudio.core.client.widget.CanFocus; import org.rstudio.studio.client.RStudioGinjector; import org.rstudio.studio.client.application.events.EventBus; public class WindowFrame extends Composite implements HasWindowStateChangeHandlers, ProvidesResize, RequiresResize, EnsureVisibleHandler, EnsureHeightHandler { public WindowFrame(Widget mainWidget) { this(); setMainWidget(mainWidget); } public WindowFrame() { RStudioGinjector.INSTANCE.injectMembers(this); final ThemeStyles styles = ThemeResources.INSTANCE.themeStyles(); border_ = new ShadowBorder(); border_.setSize("100%", "100%"); borderPositioner_ = new SimplePanel(); borderPositioner_.add(border_); HTML maximize = new HTML(); maximize.setStylePrimaryName(styles.maximize()); maximize.addStyleName(ThemeStyles.INSTANCE.handCursor()); maximize.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { maximize(); } }); HTML minimize = new HTML(); minimize.setStylePrimaryName(styles.minimize()); minimize.addStyleName(ThemeStyles.INSTANCE.handCursor()); minimize.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { minimize(); } }); frame_ = new LayoutPanel(); frame_.setStylePrimaryName(styles.windowframe()); frame_.addStyleName(styles.windowFrameObject()); frame_.add(borderPositioner_); frame_.setWidgetTopBottom(borderPositioner_, 0, Style.Unit.PX, 0, Style.Unit.PX); frame_.setWidgetLeftRight(borderPositioner_, 0, Style.Unit.PX, 0, Style.Unit.PX); frame_.add(maximize); frame_.setWidgetTopHeight(maximize, ShadowBorder.TOP_SHADOW_WIDTH + 4, Style.Unit.PX, 14, Style.Unit.PX); frame_.setWidgetRightWidth(maximize, ShadowBorder.RIGHT_SHADOW_WIDTH + 7, Style.Unit.PX, 14, Style.Unit.PX); frame_.add(minimize); frame_.setWidgetTopHeight(minimize, ShadowBorder.TOP_SHADOW_WIDTH + 4, Style.Unit.PX, 14, Style.Unit.PX); frame_.setWidgetRightWidth(minimize, ShadowBorder.RIGHT_SHADOW_WIDTH + 25, Style.Unit.PX, 14, Style.Unit.PX); buttonsArea_ = new FlowPanel(); frame_.add(buttonsArea_); initWidget(frame_); } @Inject private void initialize(EventBus events) { events_ = events; } @Override public void setVisible(boolean visible) { super.setVisible(visible); if (main_ instanceof RequiresVisibilityChanged) ((RequiresVisibilityChanged)main_).onVisibilityChanged(visible); if (fill_ instanceof RequiresVisibilityChanged) ((RequiresVisibilityChanged)fill_).onVisibilityChanged(visible); if (header_ instanceof RequiresVisibilityChanged) ((RequiresVisibilityChanged)header_).onVisibilityChanged(visible); } private void maximize() { fireEvent(new WindowStateChangeEvent(WindowState.MAXIMIZE)); } private void minimize() { fireEvent(new WindowStateChangeEvent(WindowState.MINIMIZE)); } public HandlerRegistration addWindowStateChangeHandler( WindowStateChangeHandler handler) { return addHandler(handler, WindowStateChangeEvent.TYPE); } public HandlerRegistration addEnsureHeightHandler( EnsureHeightHandler handler) { return addHandler(handler, EnsureHeightEvent.TYPE); } /** * Puts a widget in the main content area (under the title bar). */ public void setMainWidget(Widget widget) { if (widget != null) setFillWidget(null); if (header_ == null) setHeaderWidget(previousHeader_); if (main_ != null) { frame_.remove(main_); main_ = null; if (ensureVisibleRegistration_ != null) { ensureVisibleRegistration_.removeHandler(); ensureVisibleRegistration_ = null; } if (ensureHeightRegistration_ != null) { ensureHeightRegistration_.removeHandler(); ensureHeightRegistration_ = null; } } main_ = widget; if (main_ != null) { if (main_ instanceof HasEnsureVisibleHandlers) { ensureVisibleRegistration_ = ((HasEnsureVisibleHandlers)main_).addEnsureVisibleHandler(this); } if (main_ instanceof HasEnsureHeightHandlers) { ensureHeightRegistration_ = ((HasEnsureHeightHandlers)main_).addEnsureHeightHandler(this); } final ThemeStyles styles = ThemeResources.INSTANCE.themeStyles(); main_.addStyleName(styles.windowFrameWidget()); frame_.add(main_); frame_.setWidgetLeftRight( main_, ShadowBorder.LEFT_SHADOW_WIDTH, Style.Unit.PX, ShadowBorder.RIGHT_SHADOW_WIDTH, Style.Unit.PX); frame_.setWidgetTopBottom(main_, ShadowBorder.CONTENT_REGION_TOP, Style.Unit.PX, ShadowBorder.BOTTOM_SHADOW_WIDTH, Style.Unit.PX); } } /** * Puts a widget in the header area (the title bar). */ public void setHeaderWidget(Widget widget) { if (widget != null) setFillWidget(null); if (header_ != null) { frame_.remove(header_); previousHeader_ = header_; header_ = null; } header_ = widget; if (header_ != null) { frame_.add(header_); frame_.setWidgetLeftRight( header_, ShadowBorder.LEFT_SHADOW_WIDTH, Style.Unit.PX, ShadowBorder.RIGHT_SHADOW_WIDTH + 39, Style.Unit.PX); frame_.setWidgetTopHeight( header_, ShadowBorder.TOP_SHADOW_WIDTH, Style.Unit.PX, ShadowBorder.TITLEBAR_REGION_BOTTOM, Style.Unit.PX); } } /** * Puts a widget in the whole space (includes both header and main content * areas--i.e. everything inside the shadow border). */ public void setFillWidget(Widget widget) { if (widget != null) { setHeaderWidget(null); setMainWidget(null); } if (fill_ != null) { frame_.remove(fill_); fill_ = null; if (ensureVisibleRegistration_ != null) { ensureVisibleRegistration_.removeHandler(); ensureVisibleRegistration_ = null; } if (ensureHeightRegistration_ != null) { ensureHeightRegistration_.removeHandler(); ensureHeightRegistration_ = null; } } fill_ = widget; if (fill_ != null) { if (fill_ instanceof HasEnsureVisibleHandlers) { ensureVisibleRegistration_ = ((HasEnsureVisibleHandlers)fill_).addEnsureVisibleHandler(this); } if (fill_ instanceof HasEnsureHeightHandlers) { ensureHeightRegistration_ = ((HasEnsureHeightHandlers)fill_).addEnsureHeightHandler(this); } frame_.add(fill_); frame_.setWidgetLeftRight(fill_, ShadowBorder.LEFT_SHADOW_WIDTH, Style.Unit.PX, ShadowBorder.RIGHT_SHADOW_WIDTH, Style.Unit.PX); frame_.setWidgetTopBottom(fill_, ShadowBorder.TOP_SHADOW_WIDTH, Style.Unit.PX, ShadowBorder.BOTTOM_SHADOW_WIDTH, Style.Unit.PX); } } public void setContextButton(Widget button, int width, int height, int position) { if (contextButtons_.containsKey(position) && contextButtons_.get(position) != null) { contextButtons_.get(position).removeFromParent(); contextButtons_.put(position, null); } if (button != null) { contextButtons_.put(position, button); button.getElement().getStyle().setFloat(Float.RIGHT); buttonsArea_.add(button); frame_.setWidgetRightWidth(buttonsArea_, 48, Unit.PX, width * contextButtons_.size(), Unit.PX); frame_.setWidgetTopHeight(buttonsArea_, 3, Unit.PX, height, Unit.PX); // Without z-index, the header widget will obscure the context button // if the former is set after the latter. frame_.getWidgetContainerElement(buttonsArea_).getStyle().setZIndex(10); button.getElement().setAttribute("display", "inline-block"); button.getElement().setAttribute("float", "right"); } } public void onResize() { if (frame_ != null) frame_.onResize(); } public void focus() { if (main_ != null) { if (main_ instanceof CanFocus) ((CanFocus)main_).focus(); } else if (fill_ != null) { if (fill_ instanceof CanFocus) ((CanFocus)fill_).focus(); } } public void onEnsureVisible(EnsureVisibleEvent event) { if (!isVisible()) fireEvent(new WindowStateChangeEvent(WindowState.NORMAL)); events_.fireEvent(new WindowEnsureVisibleEvent(this)); } @Override public void onEnsureHeight(EnsureHeightEvent event) { fireEvent(event); } public void onBeforeShow() { if (main_ instanceof BeforeShowCallback) ((BeforeShowCallback)main_).onBeforeShow(); if (fill_ instanceof BeforeShowCallback) ((BeforeShowCallback)fill_).onBeforeShow(); } public Widget getFillWidget() { return fill_; } private final LayoutPanel frame_; private final ShadowBorder border_; private final SimplePanel borderPositioner_; private Widget main_; private Widget header_; private Widget fill_; private HashMap<Integer, Widget> contextButtons_ = new HashMap<Integer, Widget>(); private HandlerRegistration ensureVisibleRegistration_; private HandlerRegistration ensureHeightRegistration_; private Widget previousHeader_; private FlowPanel buttonsArea_; // Injected ---- private EventBus events_; }