/* * Copyright 2003-2015 JetBrains s.r.o. * * 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 jetbrains.mps.nodeEditor.cells; import jetbrains.mps.nodeEditor.EditorSettings; import jetbrains.mps.nodeEditor.cells.contextAssistant.ContextAssistantController; import jetbrains.mps.nodeEditor.cells.contextAssistant.ContextAssistantPanel; import jetbrains.mps.nodeEditor.cells.contextAssistant.FocusUtil; import jetbrains.mps.nodeEditor.cells.contextAssistant.WhatsThisActionItem; import jetbrains.mps.openapi.editor.EditorComponent; import jetbrains.mps.openapi.editor.EditorContext; import jetbrains.mps.openapi.editor.assist.ContextAssistant; import org.jetbrains.annotations.NotNull; import jetbrains.mps.openapi.editor.style.StyleRegistry; import org.jetbrains.mps.openapi.model.SNode; import javax.swing.AbstractAction; import javax.swing.JComponent; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; public class EditorCell_ContextAssistantComponent extends EditorCell_ComponentBase { private final ContextAssistantController myController; private final ContextAssistantPanel myPanel; private final TriggerRelayoutComponentListener myComponentListener = new TriggerRelayoutComponentListener(); public EditorCell_ContextAssistantComponent(EditorContext editorContext, SNode node) { super(editorContext, node); myPanel = new ContextAssistantPanel(); myPanel.setBackground(StyleRegistry.getInstance().getEditorBackground()); myPanel.setEscapeAction(new RequestFocusInEditorAction(editorContext.getEditorComponent())); myController = new ContextAssistantController(editorContext, myPanel); myController.setHelpAction(new WhatsThisActionItem(myPanel.getComponent())); myController.hideMenu(); } @NotNull @Override public JComponent getComponent() { return myPanel.getComponent(); } @Override public int getAscent() { return myPanel.getBaseline(); } @Override public void onAdd() { super.onAdd(); getContext().getContextAssistantManager().register(myController); // Relayout the cell when the panel appears/disappears, mainly to ensure that the horizontal scrollbar appears or disappears as necessary. myPanel.getComponent().addComponentListener(myComponentListener); } @Override public void onRemove() { myPanel.getComponent().removeComponentListener(myComponentListener); getContext().getContextAssistantManager().unregister(myController); super.onRemove(); } @Override public void moveTo(int x, int y) { super.moveTo(x, y); myPanel.setMaximumWidth(EditorSettings.getInstance().getVerticalBoundWidth() - x); } @Override public void setX(int x) { super.setX(x); myPanel.setMaximumWidth(EditorSettings.getInstance().getVerticalBoundWidth() - x); } @Override public void relayoutImpl() { JComponent component = getComponent(); setWidth(component.isVisible() ? component.getWidth() : 0); setHeight(myPanel.getPreferredHeight() - 1); // do not count the bottom border, hence -1 } @Override public void layoutComponent() { // Do nothing. Our cell size is updated via the component listener and the superclass behavior would cause endless back-and-forth resizing since // the component doesn't have a preferred size. } public ContextAssistant getContextAssistant() { return myController; } private static class RequestFocusInEditorAction extends AbstractAction { private final EditorComponent myEditorComponent; RequestFocusInEditorAction(EditorComponent editorComponent) { myEditorComponent = editorComponent; } @Override public void actionPerformed(ActionEvent e) { FocusUtil.requestFocus((Component) myEditorComponent, true); } } private class TriggerRelayoutComponentListener extends ComponentAdapter { @Override public void componentShown(ComponentEvent e) { triggerRelayout(); } @Override public void componentHidden(ComponentEvent e) { triggerRelayout(); } @Override public void componentResized(ComponentEvent e) { triggerRelayout(); } private void triggerRelayout() { requestRelayout(); jetbrains.mps.nodeEditor.EditorComponent editorComponent = (jetbrains.mps.nodeEditor.EditorComponent) getEditorComponent(); editorComponent.relayout(); } } }