// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.collide.client.code; import com.google.collide.client.AppContext; import com.google.collide.client.code.autocomplete.integration.AutocompleteUiController; import com.google.collide.client.code.debugging.DebuggingModelRenderer; import com.google.collide.client.code.debugging.DebuggingSidebar; import com.google.collide.client.code.debugging.EvaluationPopupController; import com.google.collide.client.code.parenmatch.ParenMatchHighlighter; import com.google.collide.client.diff.DeltaInfoBar; import com.google.collide.client.diff.EditorDiffContainer; import com.google.collide.client.editor.Editor; import com.google.collide.client.editor.renderer.LineNumberRenderer; import com.google.collide.client.filehistory.FileHistory; import com.google.collide.client.filehistory.TimelineNode; import com.google.collide.client.history.Place; import com.google.collide.client.syntaxhighlighter.SyntaxHighlighterRenderer; import com.google.collide.client.util.Elements; import com.google.collide.client.util.ResizeController; import com.google.collide.client.workspace.Header; import com.google.collide.codemirror2.CodeMirror2; import com.google.collide.mvp.CompositeView; import com.google.collide.mvp.UiComponent; import com.google.gwt.resources.client.CssResource; import elemental.css.CSSStyleDeclaration; import elemental.html.DivElement; import elemental.html.Element; // TODO: Rename the editor package to the code package since it should // encapsulate the CodePerspective. Then move code editor code to editor.core etc... /** * Presenter for the code perspective. * * Contains: * * 1. Project navigation tree for current workspace. * * 2. Our working content area (where will attach the editor). * * 3. Right sidebar (where will attach debugging state panel). * * 4. Content area header (where will be shown path to the file, and other * controls). * */ public class CodePerspective extends UiComponent<CodePerspective.View> { /** * Static factory method for obtaining an instance of the CodePerspective. */ public static CodePerspective create(View view, Place currentPlace, WorkspaceNavigation nav, EditableContentArea contentArea, AppContext context) { CodePerspective codePerspective = new CodePerspective(view, currentPlace, nav, contentArea, context); codePerspective.initResizeControllers(); return codePerspective; } /** * CSS and images used by the CodePerspective. */ public interface Resources extends Header.Resources, FileHistory.Resources, TimelineNode.Resources, WorkspaceNavigation.Resources, EditorDiffContainer.Resources, Editor.Resources, SyntaxHighlighterRenderer.Resources, LineNumberRenderer.Resources, ParenMatchHighlighter.Resources, DebuggingModelRenderer.Resources, DebuggingSidebar.Resources, EvaluationPopupController.Resources, DeltaInfoBar.Resources, CodeMirror2.Resources, EditableContentArea.Resources, AutocompleteUiController.Resources { @Source({"CodePerspective.css", "com/google/collide/client/common/constants.css"}) Css codePerspectiveCss(); } /** * Style names. */ public interface Css extends CssResource { String base(); int collapsedRightSplitterRight(); String navArea(); int navWidth(); String resizing(); String splitter(); String rightSplitter(); int splitterWidth(); int splitterOverlap(); String rightSidebarContentContainer(); } /** * The View for the CodePerspective. */ public static class View extends CompositeView<Void> { private final Resources res; private final Css css; private final WorkspaceNavigation.View navView; private final EditableContentArea.View contentView; /** * Wrapper element for the WorkspaceNavigation.View. We need a wrapper * because of the behavior of flex box. */ private DivElement navArea; /** Splitter between the navigator and content area. */ private DivElement splitter; /** Splitter between the content area and right sidebar. */ private DivElement rightSplitter; /** Container for the right sidebar. */ private DivElement rightSidebarContentContainer; public View(Resources res) { this.res = res; this.css = res.codePerspectiveCss(); this.navView = new WorkspaceNavigation.View(res); this.contentView = new EditableContentArea.View(res); // Create the DOM and connect the elements together. setElement(Elements.createDivElement(css.base())); createDom(); } public Element getSidebarElement() { return rightSidebarContentContainer; } public Element getNavigationElement() { return navArea; } public WorkspaceNavigation.View getNavigationView() { return navView; } public EditableContentArea.View getContentView() { return contentView; } public Element getSplitter() { return splitter; } public Element getRightSplitter() { return rightSplitter; } public Element getRightSidebarElement() { return rightSidebarContentContainer; } /** * Create the initial DOM structure for the workspace shell. */ private void createDom() { // Instantiate DOM elems. navArea = Elements.createDivElement(css.navArea()); splitter = Elements.createDivElement(css.splitter()); rightSplitter = Elements.createDivElement(css.rightSplitter()); rightSidebarContentContainer = Elements.createDivElement(css.rightSidebarContentContainer()); Element elem = getElement(); navArea.appendChild(navView.getElement()); elem.appendChild(navArea); elem.appendChild(splitter); elem.appendChild(contentView.getElement()); // Attach the right sidebar and splitter to the base element of the // WorkspaceContentArea.View. contentView.getElement().appendChild(rightSplitter); contentView.getElement().appendChild(rightSidebarContentContainer); rightSidebarContentContainer.getStyle().setVisibility(CSSStyleDeclaration.Visibility.HIDDEN); } } final WorkspaceNavigation nav; final EditableContentArea contentArea; private ResizeController leftResizeController; private ResizeController rightResizeController; private final Place currentPlace; CodePerspective(View view, Place currentPlace, WorkspaceNavigation nav, EditableContentArea contentArea, AppContext context) { super(view); this.currentPlace = currentPlace; this.nav = nav; this.contentArea = contentArea; } public EditableContentArea getContentArea() { return contentArea; } private void initResizeControllers() { View view = getView(); leftResizeController = new NavigatorAreaResizeController(currentPlace, view.res, view.splitter, view.navArea, view.contentView.getElement(), view.css.splitterWidth(), view.css.splitterOverlap()); leftResizeController.start(); rightResizeController = new RightSidebarResizeController(currentPlace, view.res, view.rightSplitter, view.rightSidebarContentContainer, view.contentView.getContentElement(), view.css.splitterWidth(), view.css.collapsedRightSplitterRight(), contentArea.getView().getDefaultEditableContentAreaRight()); rightResizeController.setNegativeDelta(true); rightResizeController.start(); } }