mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Inplace editing
This commit is contained in:
+6
-2
@@ -193,9 +193,13 @@ public class PropertyParser {
|
||||
Class<?> superComponentClass = componentClass.getSuperclass();
|
||||
if (superComponentClass != null) {
|
||||
superComponentClass = configureClass(superComponentClass);
|
||||
MetaModel superModel = myMetaManager.getModelByTarget(superComponentClass.getName());
|
||||
|
||||
List<Property> superProperties = loadWidgetProperties(superComponentClass,
|
||||
myMetaManager.getModelByTarget(superComponentClass.getName()));
|
||||
if (model != null && superModel != null && model.getInplaceProperties().isEmpty()) {
|
||||
model.setInplaceProperties(superModel.getInplaceProperties());
|
||||
}
|
||||
|
||||
List<Property> superProperties = loadWidgetProperties(superComponentClass, superModel);
|
||||
for (Property superProperty : superProperties) {
|
||||
if (PropertyTable.findProperty(properties, superProperty) == -1) {
|
||||
if (model == null) {
|
||||
|
||||
+47
-26
@@ -22,6 +22,7 @@ import com.intellij.designer.model.MetaManager;
|
||||
import com.intellij.designer.model.MetaModel;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.propertyTable.Property;
|
||||
import com.intellij.designer.propertyTable.PropertyTable;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -50,32 +51,6 @@ public class RadCustomViewComponent extends RadViewComponent implements IConfigu
|
||||
"\"/>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaModel getMetaModelForProperties() throws Exception {
|
||||
MetaModel metaModel = getClientProperty(MODEL_KEY);
|
||||
|
||||
if (metaModel == null) {
|
||||
Module module = getRoot().getClientProperty(ModelParser.MODULE_KEY);
|
||||
MetaManager metaManager = ViewsMetaManager.getInstance(module.getProject());
|
||||
PsiClass viewClass = ChooseClassDialog.findClass(module, getViewClass());
|
||||
|
||||
while (viewClass != null) {
|
||||
metaModel = metaManager.getModelByTarget(viewClass.getQualifiedName());
|
||||
if (metaModel != null) {
|
||||
break;
|
||||
}
|
||||
viewClass = viewClass.getSuperClass();
|
||||
}
|
||||
if (metaModel == null) {
|
||||
metaModel = myMetaModel;
|
||||
}
|
||||
|
||||
setClientProperty(MODEL_KEY, metaModel);
|
||||
}
|
||||
|
||||
return metaModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(RadComponent rootComponent) throws Exception {
|
||||
String view = chooseView(rootComponent);
|
||||
@@ -126,6 +101,52 @@ public class RadCustomViewComponent extends RadViewComponent implements IConfigu
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaModel getMetaModelForProperties() throws Exception {
|
||||
MetaModel metaModel = getClientProperty(MODEL_KEY);
|
||||
|
||||
if (metaModel == null) {
|
||||
Module module = getRoot().getClientProperty(ModelParser.MODULE_KEY);
|
||||
MetaManager metaManager = ViewsMetaManager.getInstance(module.getProject());
|
||||
PsiClass viewClass = ChooseClassDialog.findClass(module, getViewClass());
|
||||
|
||||
while (viewClass != null) {
|
||||
metaModel = metaManager.getModelByTarget(viewClass.getQualifiedName());
|
||||
if (metaModel != null) {
|
||||
break;
|
||||
}
|
||||
viewClass = viewClass.getSuperClass();
|
||||
}
|
||||
if (metaModel == null) {
|
||||
metaModel = myMetaModel;
|
||||
}
|
||||
|
||||
setClientProperty(MODEL_KEY, metaModel);
|
||||
}
|
||||
|
||||
return metaModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Property> getInplaceProperties() throws Exception {
|
||||
List<Property> properties = new ArrayList<Property>();
|
||||
MetaModel metaModel = getMetaModelForProperties();
|
||||
List<Property> allProperties = getProperties();
|
||||
|
||||
properties.add(CLASS_PROPERTY);
|
||||
|
||||
for (String name : metaModel.getInplaceProperties()) {
|
||||
Property property = PropertyTable.findProperty(allProperties, name);
|
||||
if (property != null) {
|
||||
properties.add(property);
|
||||
}
|
||||
}
|
||||
|
||||
properties.add(PropertyTable.findProperty(allProperties, "id"));
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(List<Property> properties) {
|
||||
List<Property> oldProperties = getProperties();
|
||||
|
||||
+11
@@ -19,6 +19,7 @@ import com.android.ide.common.rendering.api.ViewInfo;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.model.RadVisualComponent;
|
||||
import com.intellij.designer.propertyTable.Property;
|
||||
import com.intellij.designer.propertyTable.PropertyTable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
@@ -196,6 +197,16 @@ public class RadViewComponent extends RadVisualComponent {
|
||||
myProperties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Property> getInplaceProperties() throws Exception {
|
||||
List<Property> properties = super.getInplaceProperties();
|
||||
Property idProperty = PropertyTable.findProperty(myProperties, "id");
|
||||
if (idProperty != null) {
|
||||
properties.add(idProperty);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(Element parent) throws Exception {
|
||||
// skip root
|
||||
|
||||
+54
-25
@@ -27,6 +27,8 @@
|
||||
|
||||
<palette title="include" icon="/com/intellij/android/designer/icons/include.png"
|
||||
tooltip="Lets you statically include XML layout inside other XML layouts."/>
|
||||
|
||||
<properties inplace="layout:xml"/>
|
||||
</meta>
|
||||
|
||||
<meta model="com.intellij.android.designer.model.RadFragment"
|
||||
@@ -37,6 +39,8 @@
|
||||
|
||||
<palette title="fragment" icon="/com/intellij/android/designer/icons/fragment.png"
|
||||
tooltip="A Fragment is a piece of an application's user interface or behavior that can be placed in an Activity."/>
|
||||
|
||||
<properties inplace="name"/>
|
||||
</meta>
|
||||
|
||||
|
||||
@@ -70,6 +74,7 @@
|
||||
tooltip="Displays text to the user and optionally allows them to edit it."/>
|
||||
|
||||
<properties
|
||||
inplace="text"
|
||||
important="text hint textColor typeface textStyle gravity editable enabled"
|
||||
expert="bufferType textScaleX cursorVisible scrollHorizontally includeFontPadding shadowDx shadowDy shadowRadius freezesText drawableTop drawableLeft drawableStart drawablePadding lineSpacingExtra lineSpacingMultiplier imeOptions privateImeOptions imeActionLabel imeActionId editorExtras textSelectHandleLeft textSelectHandleRight textSelectHandle textEditPasteWindowLayout textEditNoPasteWindowLayout textEditSideNoPasteWindowLayout textEditSuggestionItemLayout textCursorDrawable textAllCaps maxEms ems minEms"
|
||||
/>
|
||||
@@ -95,6 +100,7 @@
|
||||
tooltip="Represents a push-button widget."/>
|
||||
|
||||
<properties
|
||||
inplace="text"
|
||||
important="onClick"
|
||||
expert="editable password autoLink linksClickable numeric digits phoneNumber inputMethod autoText inputType textIsSelectable"
|
||||
/>
|
||||
@@ -111,7 +117,8 @@
|
||||
</meta>
|
||||
|
||||
<meta class="android.widget.CompoundButton">
|
||||
<properties important="checked button"/>
|
||||
<properties inplace="text checked"
|
||||
important="checked button"/>
|
||||
</meta>
|
||||
|
||||
<meta model="com.intellij.android.designer.model.RadViewComponent"
|
||||
@@ -205,7 +212,7 @@
|
||||
<palette title="CheckedTextView" icon="/com/intellij/android/designer/icons/CheckedTextView.png"
|
||||
tooltip="An extension to TextView that supports the Checkable interface."/>
|
||||
|
||||
<properties important="checked checkMark"/>
|
||||
<properties inplace="text checked" important="checked checkMark"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -247,6 +254,8 @@
|
||||
<palette title="AutoCompleteTextView" icon="/com/intellij/android/designer/icons/AutoCompleteTextView.png"
|
||||
tooltip="An editable text view that shows completion suggestions automatically while the user is typing."/>
|
||||
|
||||
<properties inplace="text inputType"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
<AutoCompleteTextView
|
||||
@@ -305,8 +314,6 @@
|
||||
<palette title="AnalogClock" icon="/com/intellij/android/designer/icons/AnalogClock.png"
|
||||
tooltip="This widget display an analogic clock with two hands for hours and minutes."/>
|
||||
|
||||
<properties important=""/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
<AnalogClock
|
||||
@@ -341,7 +348,8 @@
|
||||
<palette title="Chronometer" icon="/com/intellij/android/designer/icons/Chronometer.png"
|
||||
tooltip="Class that implements a simple timer."/>
|
||||
|
||||
<properties important="format"/>
|
||||
<properties inplace="text format"
|
||||
important="format"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -411,7 +419,8 @@
|
||||
<palette title="ProgressBar" icon="/com/intellij/android/designer/icons/ProgressBar.png"
|
||||
tooltip="Visual indicator of progress in some operation."/>
|
||||
|
||||
<properties important="max progress indeterminate"/>
|
||||
<properties inplace="max progress indeterminate"
|
||||
important="max progress indeterminate"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -447,7 +456,9 @@
|
||||
<palette title="RatingBar" icon="/com/intellij/android/designer/icons/RatingBar.png"
|
||||
tooltip="A RatingBar is an extension of SeekBar and ProgressBar that shows a rating in stars."/>
|
||||
|
||||
<properties important="numStars rating stepSize" expert="max progress indeterminate isIndicator"/>
|
||||
<properties inplace="numStars rating stepSize"
|
||||
important="numStars rating stepSize"
|
||||
expert="max progress indeterminate isIndicator"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -466,7 +477,8 @@
|
||||
<palette title="ImageView" icon="/com/intellij/android/designer/icons/ImageView.png"
|
||||
tooltip="Displays an arbitrary image, such as an icon."/>
|
||||
|
||||
<properties important="src"/>
|
||||
<properties inplace="src"
|
||||
important="src"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -572,7 +584,8 @@
|
||||
<palette title="GestureOverlayView" icon="/com/intellij/android/designer/icons/GestureOverlayView.png"
|
||||
tooltip="A transparent overlay for gesture input that can be placed on top of other widgets or contain other widgets."/>
|
||||
|
||||
<properties important="gestureColor orientation"/>
|
||||
<properties inplace="gestureColor orientation"
|
||||
important="gestureColor orientation"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -592,7 +605,8 @@
|
||||
<palette title="ViewStub" icon="/com/intellij/android/designer/icons/ViewStub.png"
|
||||
tooltip="A ViewStub is an invisible, zero-sized View that can be used to lazily inflate layout resources at runtime."/>
|
||||
|
||||
<properties important="layout inflatedId"/>
|
||||
<properties inplace="layout inflatedId"
|
||||
important="layout inflatedId"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -652,8 +666,8 @@
|
||||
<palette title="TimePicker" icon="/com/intellij/android/designer/icons/TimePicker.png"
|
||||
tooltip="A view for selecting the time of day, in either 24 hour or AM/PM mode."/>
|
||||
|
||||
<properties
|
||||
important="layout"/>
|
||||
<properties inplace="layout"
|
||||
important="layout"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -706,7 +720,8 @@
|
||||
<palette title="SearchView" icon="/com/intellij/android/designer/icons/SearchView.png"
|
||||
tooltip="A widget that provides a user interface for the user to enter a search query and submit a request to a search provider. Shows a list of query suggestions or results, if available, and allows the user to pick a suggestion or result to launch into."/>
|
||||
|
||||
<properties important="iconifiedByDefault queryHint imeOptions inputType"/>
|
||||
<properties inplace="queryHint inputType"
|
||||
important="iconifiedByDefault queryHint imeOptions inputType"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -719,7 +734,8 @@
|
||||
</meta>
|
||||
|
||||
<meta class="android.widget.AbsListView">
|
||||
<properties important="choiceMode"/>
|
||||
<properties inplace="choiceMode"
|
||||
important="choiceMode"/>
|
||||
</meta>
|
||||
|
||||
<meta model="com.intellij.android.designer.model.RadViewComponent"
|
||||
@@ -767,7 +783,8 @@
|
||||
<palette title="GridView" icon="/com/intellij/android/designer/icons/GridView.png"
|
||||
tooltip="A view that shows items in two-dimensional scrolling grid. The items in the grid come from the ListAdapter associated with this view."/>
|
||||
|
||||
<properties important="horizontalSpacing verticalSpacing stretchMode columnWidth numColumns gravity"/>
|
||||
<properties inplace="numColumns"
|
||||
important="horizontalSpacing verticalSpacing stretchMode columnWidth numColumns gravity"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -804,7 +821,8 @@
|
||||
<palette title="ScrollView" icon="/com/intellij/android/designer/icons/ScrollView.png"
|
||||
tooltip="Layout container for a view hierarchy that can be scrolled by the user, allowing it to be larger than the physical display. ScrollView only supports vertical scrolling."/>
|
||||
|
||||
<properties important="fillViewport"/>
|
||||
<properties inplace="fillViewport"
|
||||
important="fillViewport"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -824,7 +842,8 @@
|
||||
<palette title="HorizontalScrollView" icon="/com/intellij/android/designer/icons/HorizontalScrollView.png"
|
||||
tooltip="Layout container for a view hierarchy that can be scrolled by the user, allowing it to be larger than the physical display."/>
|
||||
|
||||
<properties important="fillViewport"/>
|
||||
<properties inplace="fillViewport"
|
||||
important="fillViewport"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -843,7 +862,8 @@
|
||||
<palette title="Gallery" icon="/com/intellij/android/designer/icons/Gallery.png"
|
||||
tooltip="A view that shows items in a center-locked, horizontally scrolling list."/>
|
||||
|
||||
<properties important="gravity"/>
|
||||
<properties inplace="gravity"
|
||||
important="gravity"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -862,7 +882,8 @@
|
||||
<palette title="Spinner" icon="/com/intellij/android/designer/icons/Spinner.png"
|
||||
tooltip="A view that displays one child at a time and lets the user pick among them."/>
|
||||
|
||||
<properties important="entries prompt spinnerMode gravity"/>
|
||||
<properties inplace="spinnerMode"
|
||||
important="entries prompt spinnerMode gravity"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -1033,7 +1054,9 @@
|
||||
<palette title="RadioGroup" icon="/com/intellij/android/designer/icons/RadioGroup.png"
|
||||
tooltip="This class is used to create a multiple-exclusion scope for a set of radio buttons. Checking one radio button that belongs to a radio group unchecks any previously checked radio button within the same group."/>
|
||||
|
||||
<properties important="orientation checkedButton" top="gravity orientation"/>
|
||||
<properties inplace="orientation checkedButton"
|
||||
important="orientation checkedButton"
|
||||
top="gravity orientation"/>
|
||||
|
||||
<creation>
|
||||
<![CDATA[
|
||||
@@ -1050,7 +1073,8 @@
|
||||
class="android.widget.TwoLineListItem"
|
||||
tag="TwoLineListItem">
|
||||
|
||||
<properties important="mode"/>
|
||||
<properties inplace="mode"
|
||||
important="mode"/>
|
||||
|
||||
<palette title="TwoLineListItem" icon="/com/intellij/android/designer/icons/TwoLineListItem.png"
|
||||
tooltip="A view group with two children, intended for use in ListViews."/>
|
||||
@@ -1156,7 +1180,9 @@
|
||||
class="android.widget.SlidingDrawer"
|
||||
tag="SlidingDrawer">
|
||||
|
||||
<properties important="orientation" expert="handle content"/>
|
||||
<properties inplace="orientation"
|
||||
important="orientation"
|
||||
expert="handle content"/>
|
||||
|
||||
<palette title="SlidingDrawer" icon="/com/intellij/android/designer/icons/SlidingDrawer.png"
|
||||
tooltip="SlidingDrawer hides content out of the screen and allows the user to drag a handle to bring the content on screen. SlidingDrawer can be used vertically or horizontally. A special widget composed of two children views: the handle, that the users drags, and the content, attached to the handle and dragged with it."/>
|
||||
@@ -1195,7 +1221,8 @@
|
||||
<palette title="LinearLayout" icon="/com/intellij/android/designer/icons/LinearLayout.png"
|
||||
tooltip="A Layout that arranges its children in a single column or a single row."/>
|
||||
|
||||
<properties important="orientation gravity baselineAligned measureWithLargestChild showDividers"
|
||||
<properties inplace="orientation"
|
||||
important="orientation gravity baselineAligned measureWithLargestChild showDividers"
|
||||
expert="layout:gravity.fill layout:gravity.clip layout:gravity.start layout:gravity.end"
|
||||
top="gravity orientation"
|
||||
/>
|
||||
@@ -1294,7 +1321,8 @@
|
||||
class="android.widget.GridLayout"
|
||||
tag="GridLayout">
|
||||
|
||||
<properties important="orientation rowCount columnCount"
|
||||
<properties inplace="orientation rowCount columnCount"
|
||||
important="orientation rowCount columnCount"
|
||||
top="rowCount columnCount"
|
||||
expert="layout:gravity.clip layout:gravity.start layout:gravity.end"
|
||||
/>
|
||||
@@ -1317,7 +1345,8 @@
|
||||
class="android.widget.RelativeLayout"
|
||||
tag="RelativeLayout">
|
||||
|
||||
<properties important="gravity"/>
|
||||
<properties inplace="gravity"
|
||||
important="gravity"/>
|
||||
|
||||
<palette title="RelativeLayout" icon="/com/intellij/android/designer/icons/RelativeLayout.png"
|
||||
tooltip="A Layout where the positions of the children can be described in relation to each other or to the parent."/>
|
||||
|
||||
+44
-4
@@ -18,6 +18,7 @@ package com.intellij.android.designer.propertyTable.editors;
|
||||
import com.android.resources.ResourceType;
|
||||
import com.intellij.android.designer.model.ModelParser;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.propertyTable.InplaceContext;
|
||||
import com.intellij.designer.propertyTable.PropertyEditor;
|
||||
import com.intellij.designer.propertyTable.editors.ComboEditor;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -26,11 +27,14 @@ import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.ComboboxWithBrowseButton;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import org.jetbrains.android.dom.attrs.AttributeFormat;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
@@ -51,7 +55,12 @@ public class ResourceEditor extends PropertyEditor {
|
||||
myTypes = types;
|
||||
|
||||
if (formats.contains(AttributeFormat.Enum) || formats.contains(AttributeFormat.Boolean)) {
|
||||
ComboboxWithBrowseButton editor = new ComboboxWithBrowseButton();
|
||||
ComboboxWithBrowseButton editor = new ComboboxWithBrowseButton() {
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return getComponentPreferredSize();
|
||||
}
|
||||
};
|
||||
|
||||
final JComboBox comboBox = editor.getComboBox();
|
||||
DefaultComboBoxModel model;
|
||||
@@ -78,18 +87,32 @@ public class ResourceEditor extends PropertyEditor {
|
||||
comboBox.setSelectedIndex(0);
|
||||
}
|
||||
else {
|
||||
myEditor = new TextFieldWithBrowseButton();
|
||||
myEditor = new TextFieldWithBrowseButton() {
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return getComponentPreferredSize();
|
||||
}
|
||||
};
|
||||
myEditor.registerKeyboardAction(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
}
|
||||
}, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
|
||||
getComboText().addActionListener(new ActionListener() {
|
||||
|
||||
JTextField textField = getComboText();
|
||||
textField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
fireValueCommitted(true, true);
|
||||
}
|
||||
});
|
||||
textField.getDocument().addDocumentListener(
|
||||
new DocumentAdapter() {
|
||||
protected void textChanged(final DocumentEvent e) {
|
||||
preferredSizeChanged();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
myEditor.addActionListener(new ActionListener() {
|
||||
@@ -106,6 +129,12 @@ public class ResourceEditor extends PropertyEditor {
|
||||
});
|
||||
}
|
||||
|
||||
private Dimension getComponentPreferredSize() {
|
||||
Dimension size1 = myEditor.getChildComponent().getPreferredSize();
|
||||
Dimension size2 = myEditor.getButton().getPreferredSize();
|
||||
return new Dimension(size1.width + size2.width + 5, size1.height);
|
||||
}
|
||||
|
||||
private static ResourceType[] convertTypes(Set<AttributeFormat> formats) {
|
||||
Set<ResourceType> types = EnumSet.noneOf(ResourceType.class);
|
||||
for (AttributeFormat format : formats) {
|
||||
@@ -141,13 +170,24 @@ public class ResourceEditor extends PropertyEditor {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getComponent(@NotNull RadComponent rootComponent, @Nullable RadComponent component, Object value) {
|
||||
public JComponent getComponent(@NotNull RadComponent rootComponent,
|
||||
@Nullable RadComponent component,
|
||||
Object value,
|
||||
@Nullable InplaceContext inplaceContext) {
|
||||
myRootComponent = rootComponent;
|
||||
JTextField text = getComboText();
|
||||
text.setText((String)value);
|
||||
if (inplaceContext != null && inplaceContext.isStartChar()) {
|
||||
text.setText(inplaceContext.getText(text.getText()));
|
||||
}
|
||||
return myEditor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return getComboText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() throws Exception {
|
||||
String value = getComboText().getText();
|
||||
|
||||
+5
-2
@@ -16,7 +16,7 @@
|
||||
package com.intellij.android.designer.propertyTable.editors;
|
||||
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.propertyTable.PropertyEditor;
|
||||
import com.intellij.designer.propertyTable.InplaceContext;
|
||||
import com.intellij.designer.propertyTable.editors.ComboEditor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -54,7 +54,10 @@ public class StringsComboEditor extends ComboEditor {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getComponent(@NotNull RadComponent rootComponent, @Nullable RadComponent component, Object value) {
|
||||
public JComponent getComponent(@NotNull RadComponent rootComponent,
|
||||
@Nullable RadComponent component,
|
||||
Object value,
|
||||
@Nullable InplaceContext inplaceContext) {
|
||||
myCombo.setSelectedItem(value);
|
||||
return myCombo;
|
||||
}
|
||||
|
||||
+2
-9
@@ -19,7 +19,6 @@ import com.intellij.designer.componentTree.ComponentTree;
|
||||
import com.intellij.designer.componentTree.ComponentTreeBuilder;
|
||||
import com.intellij.designer.componentTree.TreeEditableArea;
|
||||
import com.intellij.designer.designSurface.DesignerEditorPanel;
|
||||
import com.intellij.designer.propertyTable.PropertyTable;
|
||||
import com.intellij.designer.propertyTable.PropertyTablePanel;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
@@ -156,10 +155,6 @@ public final class DesignerToolWindowManager implements ProjectComponent {
|
||||
return editors.length > 0 ? getDesigner(editors[0]) : null;
|
||||
}
|
||||
|
||||
public PropertyTable getPropertyTable() {
|
||||
return myPropertyTablePanel.getPropertyTable();
|
||||
}
|
||||
|
||||
private void bindToDesigner(final DesignerEditorPanel designer) {
|
||||
myWindowQueue.cancelAllUpdates();
|
||||
myWindowQueue.queue(new Update("update") {
|
||||
@@ -177,14 +172,12 @@ public final class DesignerToolWindowManager implements ProjectComponent {
|
||||
clearTreeBuilder();
|
||||
myComponentTree.newModel();
|
||||
if (designer == null) {
|
||||
myComponentTree.setDecorator(null);
|
||||
myComponentTree.setActionPanel(null);
|
||||
myComponentTree.setDesignerPanel(null);
|
||||
myPropertyTablePanel.getPropertyTable().setArea(null, null);
|
||||
myToolWindow.setAvailable(false, null);
|
||||
}
|
||||
else {
|
||||
myComponentTree.setDecorator(designer.getTreeDecorator());
|
||||
myComponentTree.setActionPanel(designer.getActionPanel());
|
||||
myComponentTree.setDesignerPanel(designer);
|
||||
myTreeBuilder = new ComponentTreeBuilder(myComponentTree, designer);
|
||||
myPropertyTablePanel.getPropertyTable().setArea(designer, myTreeBuilder.getTreeArea());
|
||||
myToolWindow.setAvailable(true, null);
|
||||
|
||||
+5
-5
@@ -65,7 +65,9 @@ public class CommonEditActionsProvider implements DeleteProvider, CopyProvider,
|
||||
|
||||
@Override
|
||||
public boolean canDeleteElement(@NotNull DataContext dataContext) {
|
||||
// TODO: InplaceEditing
|
||||
if (myDesigner.getInplaceEditingLayer().isEditing()) {
|
||||
return false;
|
||||
}
|
||||
List<RadComponent> selection = getArea().getSelection();
|
||||
if (selection.isEmpty()) {
|
||||
return false;
|
||||
@@ -143,8 +145,7 @@ public class CommonEditActionsProvider implements DeleteProvider, CopyProvider,
|
||||
|
||||
@Override
|
||||
public boolean isCopyEnabled(@NotNull DataContext dataContext) {
|
||||
// TODO: InplaceEditing
|
||||
return !getArea().getSelection().isEmpty();
|
||||
return !myDesigner.getInplaceEditingLayer().isEditing() && !getArea().getSelection().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -185,8 +186,7 @@ public class CommonEditActionsProvider implements DeleteProvider, CopyProvider,
|
||||
|
||||
@Override
|
||||
public boolean isPasteEnabled(@NotNull DataContext dataContext) {
|
||||
// TODO: InplaceEditing
|
||||
return getSerializedComponentData() != null;
|
||||
return !myDesigner.getInplaceEditingLayer().isEditing() && getSerializedComponentData() != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+8
@@ -48,6 +48,8 @@ public class DesignerActionPanel implements DataProvider {
|
||||
myCommonEditActionsProvider = new CommonEditActionsProvider(designer);
|
||||
myShortcuts = shortcuts;
|
||||
|
||||
createInplaceEditingAction(myShortcuts).setDesignerPanel(designer);
|
||||
|
||||
myActionGroup.add(myStaticGroup);
|
||||
myActionGroup.add(myDynamicGroup);
|
||||
|
||||
@@ -91,6 +93,12 @@ public class DesignerActionPanel implements DataProvider {
|
||||
});
|
||||
}
|
||||
|
||||
public static StartInplaceEditing createInplaceEditingAction(JComponent shortcuts) {
|
||||
StartInplaceEditing action = new StartInplaceEditing();
|
||||
action.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)), shortcuts);
|
||||
return action;
|
||||
}
|
||||
|
||||
private void registerAction(AnAction action, @NonNls String actionId) {
|
||||
action.registerCustomShortcutSet(
|
||||
ActionManager.getInstance().getAction(actionId).getShortcutSet(),
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 com.intellij.designer.actions;
|
||||
|
||||
import com.intellij.designer.designSurface.DesignerEditorPanel;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public class StartInplaceEditing extends AnAction {
|
||||
private DesignerEditorPanel myDesigner;
|
||||
|
||||
public void setDesignerPanel(@Nullable DesignerEditorPanel designer) {
|
||||
myDesigner = designer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent event) {
|
||||
boolean enabled = false;
|
||||
|
||||
if (myDesigner != null) {
|
||||
List<RadComponent> selection = myDesigner.getSurfaceArea().getSelection();
|
||||
if (selection.size() == 1) {
|
||||
try {
|
||||
enabled = !selection.get(0).getInplaceProperties().isEmpty();
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event.getPresentation().setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
myDesigner.getInplaceEditingLayer().startEditing(null);
|
||||
}
|
||||
}
|
||||
+14
-7
@@ -16,6 +16,8 @@
|
||||
package com.intellij.designer.componentTree;
|
||||
|
||||
import com.intellij.designer.actions.DesignerActionPanel;
|
||||
import com.intellij.designer.actions.StartInplaceEditing;
|
||||
import com.intellij.designer.designSurface.DesignerEditorPanel;
|
||||
import com.intellij.designer.designSurface.FeedbackTreeLayer;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
@@ -35,6 +37,7 @@ import java.awt.*;
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public final class ComponentTree extends Tree implements DataProvider {
|
||||
private final StartInplaceEditing myInplaceEditingAction;
|
||||
private TreeComponentDecorator myDecorator;
|
||||
private DesignerActionPanel myActionPanel;
|
||||
private RadComponent myMarkComponent;
|
||||
@@ -55,20 +58,24 @@ public final class ComponentTree extends Tree implements DataProvider {
|
||||
// Install convenient keyboard navigation
|
||||
TreeUtil.installActions(this);
|
||||
|
||||
// TODO: F2 should start inplace editing
|
||||
myInplaceEditingAction = DesignerActionPanel.createInplaceEditingAction(this);
|
||||
}
|
||||
|
||||
public void newModel() {
|
||||
setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
|
||||
}
|
||||
|
||||
public void setDecorator(@Nullable TreeComponentDecorator decorator) {
|
||||
myDecorator = decorator;
|
||||
public void setDesignerPanel(@Nullable DesignerEditorPanel designer) {
|
||||
if (designer == null) {
|
||||
myDecorator = null;
|
||||
myActionPanel = null;
|
||||
}
|
||||
else {
|
||||
myDecorator = designer.getTreeDecorator();
|
||||
myActionPanel = designer.getActionPanel();
|
||||
}
|
||||
myMarkComponent = null;
|
||||
}
|
||||
|
||||
public void setActionPanel(@Nullable DesignerActionPanel actionPanel) {
|
||||
myActionPanel = actionPanel;
|
||||
myInplaceEditingAction.setDesignerPanel(designer);
|
||||
}
|
||||
|
||||
public void mark(RadComponent component, int feedback) {
|
||||
|
||||
+14
@@ -24,6 +24,7 @@ import com.intellij.designer.designSurface.tools.*;
|
||||
import com.intellij.designer.model.FindComponentVisitor;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.palette.Item;
|
||||
import com.intellij.designer.propertyTable.InplaceContext;
|
||||
import com.intellij.designer.propertyTable.Property;
|
||||
import com.intellij.diagnostic.LogMessageEx;
|
||||
import com.intellij.diagnostic.errordialog.Attachment;
|
||||
@@ -97,6 +98,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
|
||||
protected GlassLayer myGlassLayer;
|
||||
private DecorationLayer myDecorationLayer;
|
||||
private FeedbackLayer myFeedbackLayer;
|
||||
private InplaceEditingLayer myInplaceEditingLayer;
|
||||
|
||||
private ListSelectionListener myPaletteListener;
|
||||
protected ToolProvider myToolProvider;
|
||||
@@ -244,6 +246,11 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
|
||||
}, command, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startInplaceEditing(@Nullable InplaceContext inplaceContext) {
|
||||
myInplaceEditingLayer.startEditing(inplaceContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showError(@NonNls String message, Throwable e) {
|
||||
DesignerEditorPanel.this.showError(message, e);
|
||||
@@ -259,6 +266,9 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
|
||||
myFeedbackLayer = new FeedbackLayer();
|
||||
myLayeredPane.add(myFeedbackLayer, LAYER_FEEDBACK);
|
||||
|
||||
myInplaceEditingLayer = new InplaceEditingLayer(this);
|
||||
myLayeredPane.add(myInplaceEditingLayer, LAYER_INPLACE_EDITING);
|
||||
|
||||
JPanel content = new JPanel(new GridBagLayout());
|
||||
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
@@ -513,6 +523,10 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
|
||||
return myActionPanel;
|
||||
}
|
||||
|
||||
public InplaceEditingLayer getInplaceEditingLayer() {
|
||||
return myInplaceEditingLayer;
|
||||
}
|
||||
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myDesignerCard.isVisible() ? myGlassLayer : myErrorPanel;
|
||||
}
|
||||
|
||||
+256
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 com.intellij.designer.designSurface;
|
||||
|
||||
import com.intellij.designer.designSurface.feedbacks.LineMarginBorder;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.propertyTable.InplaceContext;
|
||||
import com.intellij.designer.propertyTable.Property;
|
||||
import com.intellij.designer.propertyTable.PropertyEditor;
|
||||
import com.intellij.designer.propertyTable.PropertyEditorListener;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CustomShortcutSet;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.wm.FocusWatcher;
|
||||
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
|
||||
import com.intellij.openapi.wm.ex.LayoutFocusTraversalPolicyExt;
|
||||
import com.intellij.uiDesigner.core.GridConstraints;
|
||||
import com.intellij.uiDesigner.core.GridLayoutManager;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
* @author Anton Katilin
|
||||
* @author Vladimir Kondratyev
|
||||
*/
|
||||
public class InplaceEditingLayer extends JComponent {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.designer.designSurface.InplaceEditingLayer");
|
||||
|
||||
private final FocusWatcher myFocusWatcher = new FocusWatcher() {
|
||||
protected void focusLostImpl(FocusEvent e) {
|
||||
Component opposite = e.getOppositeComponent();
|
||||
if (e.isTemporary() || opposite != null && SwingUtilities.isDescendingFrom(opposite, getTopComponent())) {
|
||||
// Do nothing if focus moves inside top component hierarchy
|
||||
return;
|
||||
}
|
||||
// [vova] we need LaterInvocator here to prevent write-access assertions
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
finishEditing(true);
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
}
|
||||
};
|
||||
private final ComponentSelectionListener mySelectionListener = new ComponentSelectionListener() {
|
||||
@Override
|
||||
public void selectionChanged(EditableArea area) {
|
||||
finishEditing(true);
|
||||
}
|
||||
};
|
||||
private PropertyEditorListener myEditorListener = new PropertyEditorListener() {
|
||||
@Override
|
||||
public void valueCommitted(PropertyEditor source, boolean continueEditing, boolean closeEditorOnError) {
|
||||
finishEditing(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editingCanceled(PropertyEditor source) {
|
||||
finishEditing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preferredSizeChanged(PropertyEditor source) {
|
||||
adjustInplaceComponentSize();
|
||||
}
|
||||
};
|
||||
private List<PropertyEditor> myEditors;
|
||||
|
||||
private final DesignerEditorPanel myDesigner;
|
||||
private JComponent myInplaceComponent;
|
||||
private int myPreferredWidth;
|
||||
|
||||
public InplaceEditingLayer(DesignerEditorPanel designer) {
|
||||
myDesigner = designer;
|
||||
}
|
||||
|
||||
public void startEditing(@Nullable InplaceContext inplaceContext) {
|
||||
try {
|
||||
List<RadComponent> selection = myDesigner.getSurfaceArea().getSelection();
|
||||
if (selection.size() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
RadComponent radComponent = selection.get(0);
|
||||
List<Property> inplaceProperties = radComponent.getInplaceProperties();
|
||||
if (inplaceProperties.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
myInplaceComponent = new JPanel(new GridLayoutManager(inplaceProperties.size(), 2));
|
||||
myInplaceComponent.setBorder(new LineMarginBorder(5, 5, 5, 5));
|
||||
new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
finishEditing(false);
|
||||
}
|
||||
}.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)), myInplaceComponent);
|
||||
|
||||
int row = 0;
|
||||
|
||||
myEditors = new ArrayList<PropertyEditor>();
|
||||
|
||||
JComponent componentToFocus = null;
|
||||
Font font = null;
|
||||
|
||||
if (inplaceContext == null) {
|
||||
inplaceContext = new InplaceContext();
|
||||
}
|
||||
|
||||
for (Property property : inplaceProperties) {
|
||||
JLabel label = new JLabel(property.getName() + ":");
|
||||
if (font == null) {
|
||||
font = label.getFont().deriveFont(Font.BOLD);
|
||||
}
|
||||
label.setFont(font);
|
||||
|
||||
myInplaceComponent.add(label,
|
||||
new GridConstraints(row, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, 0, 0, null, null,
|
||||
null));
|
||||
|
||||
PropertyEditor editor = property.getEditor();
|
||||
myEditors.add(editor);
|
||||
|
||||
JComponent component = editor.getComponent(radComponent.getRoot(), radComponent, property.getValue(radComponent), inplaceContext);
|
||||
|
||||
myInplaceComponent.add(component,
|
||||
new GridConstraints(row++, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, 0, 0,
|
||||
null, null, null));
|
||||
|
||||
if (componentToFocus == null) {
|
||||
componentToFocus = editor.getPreferredFocusedComponent();
|
||||
}
|
||||
}
|
||||
|
||||
for (PropertyEditor editor : myEditors) {
|
||||
editor.addPropertyEditorListener(myEditorListener);
|
||||
}
|
||||
|
||||
Rectangle bounds = radComponent.getBounds(this);
|
||||
Dimension size = myInplaceComponent.getPreferredSize();
|
||||
myPreferredWidth = size.width;
|
||||
myInplaceComponent.setBounds(bounds.x, bounds.y, size.width, size.height);
|
||||
add(myInplaceComponent);
|
||||
|
||||
if (componentToFocus == null) {
|
||||
componentToFocus = IdeFocusTraversalPolicy.getPreferredFocusedComponent(myInplaceComponent);
|
||||
}
|
||||
if (componentToFocus != null) {
|
||||
componentToFocus.requestFocusInWindow();
|
||||
}
|
||||
else {
|
||||
myInplaceComponent.requestFocusInWindow();
|
||||
}
|
||||
|
||||
myDesigner.getSurfaceArea().addSelectionListener(mySelectionListener);
|
||||
myFocusWatcher.install(myInplaceComponent);
|
||||
|
||||
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
|
||||
repaint();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void finishEditing(boolean commit) {
|
||||
myDesigner.getSurfaceArea().removeSelectionListener(mySelectionListener);
|
||||
|
||||
if (myInplaceComponent != null) {
|
||||
if (commit) {
|
||||
// TODO: Auto-generated method stub
|
||||
}
|
||||
|
||||
for (PropertyEditor editor : myEditors) {
|
||||
editor.removePropertyEditorListener(myEditorListener);
|
||||
}
|
||||
|
||||
removeInplaceComponent();
|
||||
myFocusWatcher.deinstall(myInplaceComponent);
|
||||
myInplaceComponent = null;
|
||||
}
|
||||
|
||||
myEditors = null;
|
||||
|
||||
myDesigner.getPreferredFocusedComponent().requestFocusInWindow();
|
||||
|
||||
disableEvents(AWTEvent.MOUSE_EVENT_MASK);
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void adjustInplaceComponentSize() {
|
||||
myInplaceComponent.revalidate();
|
||||
Dimension size = myInplaceComponent.getPreferredSize();
|
||||
int width = Math.max(size.width, myPreferredWidth);
|
||||
width = Math.min(width, getWidth() - myInplaceComponent.getX());
|
||||
myInplaceComponent.setSize(width, myInplaceComponent.getHeight());
|
||||
myInplaceComponent.revalidate();
|
||||
System.out.println("size: " + width);
|
||||
}
|
||||
|
||||
private void removeInplaceComponent() {
|
||||
// [vova] before removing component from Swing tree we have to
|
||||
// request component into glass layer. Otherwise focus from component being removed
|
||||
// can go to some RadComponent.
|
||||
|
||||
LayoutFocusTraversalPolicyExt.setOverridenDefaultComponent(myDesigner.getPreferredFocusedComponent());
|
||||
try {
|
||||
remove(myInplaceComponent);
|
||||
}
|
||||
finally {
|
||||
LayoutFocusTraversalPolicyExt.setOverridenDefaultComponent(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When there is an inplace editor we "listen" all mouse event
|
||||
* and finish editing by any MOUSE_PRESSED or MOUSE_RELEASED event.
|
||||
* We are acting like yet another glass pane over the standard glass layer.
|
||||
*/
|
||||
protected void processMouseEvent(MouseEvent e) {
|
||||
if (myInplaceComponent != null && (MouseEvent.MOUSE_PRESSED == e.getID() || MouseEvent.MOUSE_RELEASED == e.getID())) {
|
||||
finishEditing(true);
|
||||
}
|
||||
// [vova] this is very important! Without this code Swing doen't close popup menu on our
|
||||
// layered pane. Swing adds MouseListeners to all component to close popup. If we do not
|
||||
// invoke super then we lock all mouse listeners.
|
||||
super.processMouseEvent(e);
|
||||
}
|
||||
|
||||
public boolean isEditing() {
|
||||
return myInplaceComponent != null;
|
||||
}
|
||||
}
|
||||
+14
@@ -17,10 +17,12 @@ package com.intellij.designer.designSurface.tools;
|
||||
|
||||
import com.intellij.designer.designSurface.EditableArea;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.propertyTable.InplaceContext;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.ActionPopupMenu;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.List;
|
||||
@@ -85,6 +87,13 @@ public class SelectionTool extends InputTool {
|
||||
handleMove(); // hack: update cursor
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleDoubleClick(int button) {
|
||||
if (button == MouseEvent.BUTTON1 && myToolProvider != null) {
|
||||
myToolProvider.startInplaceEditing(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleMove() {
|
||||
if (myState == STATE_INIT) {
|
||||
@@ -190,6 +199,11 @@ public class SelectionTool extends InputTool {
|
||||
if (myTracker != null) {
|
||||
myTracker.keyTyped(event, area);
|
||||
}
|
||||
else if (myToolProvider != null &&
|
||||
Character.isLetterOrDigit(event.getKeyChar()) &&
|
||||
(event.getModifiers() & (InputEvent.ALT_MASK | InputEvent.CTRL_MASK)) == 0) {
|
||||
myToolProvider.startInplaceEditing(new InplaceContext(event.getKeyChar()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -17,6 +17,7 @@ package com.intellij.designer.designSurface.tools;
|
||||
|
||||
import com.intellij.designer.designSurface.EditOperation;
|
||||
import com.intellij.designer.designSurface.EditableArea;
|
||||
import com.intellij.designer.propertyTable.InplaceContext;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -133,4 +134,6 @@ public abstract class ToolProvider {
|
||||
public abstract boolean execute(ThrowableRunnable<Exception> operation, String command, boolean updateProperties);
|
||||
|
||||
public abstract void execute(List<EditOperation> operations, String command);
|
||||
|
||||
public abstract void startInplaceEditing(@Nullable InplaceContext inplaceContext);
|
||||
}
|
||||
@@ -114,6 +114,11 @@ public abstract class MetaManager {
|
||||
|
||||
Element properties = element.getChild("properties");
|
||||
if (properties != null) {
|
||||
Attribute inplace = properties.getAttribute("inplace");
|
||||
if (inplace != null) {
|
||||
meta.setInplaceProperties(StringUtil.split(inplace.getValue(), " "));
|
||||
}
|
||||
|
||||
Attribute top = properties.getAttribute("top");
|
||||
if (top != null) {
|
||||
meta.setTopProperties(StringUtil.split(top.getValue(), " "));
|
||||
|
||||
@@ -39,6 +39,7 @@ public class MetaModel {
|
||||
private Icon myIcon;
|
||||
private String myCreation;
|
||||
private boolean myDelete = true;
|
||||
private List<String> myInplaceProperties = Collections.emptyList();
|
||||
private List<String> myTopProperties = Collections.emptyList();
|
||||
private List<String> myNormalProperties = Collections.emptyList();
|
||||
private List<String> myImportantProperties = Collections.emptyList();
|
||||
@@ -116,6 +117,14 @@ public class MetaModel {
|
||||
myPaletteItem.setMetaModel(this);
|
||||
}
|
||||
|
||||
public List<String> getInplaceProperties() {
|
||||
return myInplaceProperties;
|
||||
}
|
||||
|
||||
public void setInplaceProperties(List<String> inplaceProperties) {
|
||||
myInplaceProperties = inplaceProperties;
|
||||
}
|
||||
|
||||
public List<String> getTopProperties() {
|
||||
return myTopProperties;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.designer.designSurface.StaticDecorator;
|
||||
import com.intellij.designer.designSurface.tools.DragTracker;
|
||||
import com.intellij.designer.designSurface.tools.InputTool;
|
||||
import com.intellij.designer.propertyTable.Property;
|
||||
import com.intellij.designer.propertyTable.PropertyTable;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -186,6 +187,22 @@ public abstract class RadComponent {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public List<Property> getInplaceProperties() throws Exception {
|
||||
List<Property> properties = new ArrayList<Property>();
|
||||
|
||||
if (myMetaModel != null) {
|
||||
List<Property> allProperties = getProperties();
|
||||
for (String name : myMetaModel.getInplaceProperties()) {
|
||||
Property property = PropertyTable.findProperty(allProperties, name);
|
||||
if (property != null) {
|
||||
properties.add(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T> T getClientProperty(@NotNull String key) {
|
||||
return (T)myClientProperties.get(key);
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 com.intellij.designer.propertyTable;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public class InplaceContext {
|
||||
private char myStartChar;
|
||||
|
||||
public InplaceContext() {
|
||||
this((char)0);
|
||||
}
|
||||
|
||||
public InplaceContext(char startChar) {
|
||||
myStartChar = startChar;
|
||||
}
|
||||
|
||||
public boolean isStartChar() {
|
||||
return myStartChar != 0;
|
||||
}
|
||||
|
||||
public String getText(String text) {
|
||||
if (text == null) {
|
||||
text = "";
|
||||
}
|
||||
|
||||
text += myStartChar;
|
||||
myStartChar = 0;
|
||||
return text;
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -29,10 +29,13 @@ public abstract class PropertyEditor {
|
||||
private final EventListenerList myListenerList = new EventListenerList();
|
||||
|
||||
@NotNull
|
||||
public abstract JComponent getComponent(@NotNull RadComponent rootComponent, @Nullable RadComponent component, Object value);
|
||||
public abstract JComponent getComponent(@NotNull RadComponent rootComponent,
|
||||
@Nullable RadComponent component,
|
||||
Object value,
|
||||
@Nullable InplaceContext inplaceContext);
|
||||
|
||||
@Nullable
|
||||
public JComponent getPreferredFocusedComponent(@NotNull JComponent component) {
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -533,7 +533,7 @@ public final class PropertyTable extends JBTable implements ComponentSelectionLi
|
||||
editCellAt(index, convertColumnIndexToView(1));
|
||||
LOG.assertTrue(editorComp != null);
|
||||
|
||||
JComponent preferredComponent = editor.getPreferredFocusedComponent((JComponent)editorComp);
|
||||
JComponent preferredComponent = editor.getPreferredFocusedComponent();
|
||||
if (preferredComponent == null) {
|
||||
preferredComponent = IdeFocusTraversalPolicy.getPreferredFocusedComponent((JComponent)editorComp);
|
||||
}
|
||||
@@ -855,7 +855,7 @@ public final class PropertyTable extends JBTable implements ComponentSelectionLi
|
||||
@Override
|
||||
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
|
||||
try {
|
||||
JComponent component = myEditor.getComponent(myDesigner.getRootComponent(), getCurrentComponent(), getValue((Property)value));
|
||||
JComponent component = myEditor.getComponent(myDesigner.getRootComponent(), getCurrentComponent(), getValue((Property)value), null);
|
||||
|
||||
if (component instanceof JComboBox) {
|
||||
component.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
|
||||
|
||||
+10
-1
@@ -16,6 +16,7 @@
|
||||
package com.intellij.designer.propertyTable.editors;
|
||||
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.propertyTable.InplaceContext;
|
||||
import com.intellij.designer.propertyTable.PropertyEditor;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -52,8 +53,16 @@ public class BooleanEditor extends PropertyEditor {
|
||||
return Boolean.valueOf(myCheckBox.isSelected());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myCheckBox;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JComponent getComponent(@NotNull RadComponent rootComponent, @Nullable RadComponent component, Object value) {
|
||||
public JComponent getComponent(@NotNull RadComponent rootComponent,
|
||||
@Nullable RadComponent component,
|
||||
Object value,
|
||||
@Nullable InplaceContext inplaceContext) {
|
||||
try {
|
||||
myInsideChange = true;
|
||||
myCheckBox.setBackground(UIUtil.getTableBackground());
|
||||
|
||||
+5
@@ -52,6 +52,11 @@ public abstract class ComboEditor extends PropertyEditor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myCombo;
|
||||
}
|
||||
|
||||
private static class ComboListeners implements PopupMenuListener, ActionListener {
|
||||
private final PropertyEditor myEditor;
|
||||
private boolean myCancelled;
|
||||
|
||||
+29
-2
@@ -16,11 +16,15 @@
|
||||
package com.intellij.designer.propertyTable.editors;
|
||||
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.propertyTable.InplaceContext;
|
||||
import com.intellij.designer.propertyTable.PropertyEditor;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
@@ -37,13 +41,36 @@ public class TextEditor extends PropertyEditor {
|
||||
fireValueCommitted(true, false);
|
||||
}
|
||||
});
|
||||
myTextField.getDocument().addDocumentListener(
|
||||
new DocumentAdapter() {
|
||||
protected void textChanged(final DocumentEvent e) {
|
||||
preferredSizeChanged();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getComponent(@NotNull RadComponent rootComponent, @Nullable RadComponent component, Object value) {
|
||||
public JComponent getComponent(@NotNull RadComponent rootComponent,
|
||||
@Nullable RadComponent component,
|
||||
Object value,
|
||||
@Nullable InplaceContext inplaceContext) {
|
||||
setEditorValue(component, value);
|
||||
myTextField.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 0));
|
||||
if (inplaceContext == null) {
|
||||
myTextField.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 0));
|
||||
}
|
||||
else {
|
||||
myTextField.setBorder(UIUtil.getTextFieldBorder());
|
||||
if (inplaceContext.isStartChar()) {
|
||||
myTextField.setText(inplaceContext.getText(myTextField.getText()));
|
||||
}
|
||||
}
|
||||
return myTextField;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myTextField;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user