| /* |
| * Copyright 2000-2009 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.uiDesigner.radComponents; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.util.Comparing; |
| import com.intellij.uiDesigner.*; |
| import com.intellij.uiDesigner.core.AbstractLayout; |
| import com.intellij.uiDesigner.designSurface.ComponentDropLocation; |
| import com.intellij.uiDesigner.lw.*; |
| import com.intellij.uiDesigner.palette.Palette; |
| import com.intellij.uiDesigner.propertyInspector.Property; |
| import com.intellij.uiDesigner.propertyInspector.PropertyEditor; |
| import com.intellij.uiDesigner.propertyInspector.PropertyRenderer; |
| import com.intellij.uiDesigner.propertyInspector.editors.string.StringEditor; |
| import com.intellij.uiDesigner.shared.BorderType; |
| import com.intellij.uiDesigner.shared.XYLayoutManager; |
| import com.intellij.uiDesigner.snapShooter.SnapshotContext; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import javax.swing.border.*; |
| import java.awt.*; |
| import java.util.ArrayList; |
| |
| /** |
| * @author Anton Katilin |
| * @author Vladimir Kondratyev |
| */ |
| public class RadContainer extends RadComponent implements IContainer { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.radComponents.RadContainer"); |
| |
| public static class Factory extends RadComponentFactory { |
| public RadComponent newInstance(ModuleProvider module, Class aClass, String id) { |
| return new RadContainer(module, aClass, id); |
| } |
| |
| public RadComponent newInstance(final Class componentClass, final String id, final Palette palette) { |
| return new RadContainer(componentClass, id, palette); |
| } |
| } |
| |
| /** |
| * value: RadComponent[] |
| */ |
| @NonNls |
| public static final String PROP_CHILDREN = "children"; |
| /** |
| * Children components |
| */ |
| private final ArrayList<RadComponent> myComponents; |
| /** |
| * Describes border's type. |
| */ |
| @NotNull private BorderType myBorderType; |
| /** |
| * Border's title. If border doesn't have any title then |
| * this member is <code>null</code>. |
| */ |
| @Nullable private StringDescriptor myBorderTitle; |
| private int myBorderTitleJustification; |
| private int myBorderTitlePosition; |
| private FontDescriptor myBorderTitleFont; |
| private ColorDescriptor myBorderTitleColor; |
| private Insets myBorderSize; |
| private ColorDescriptor myBorderColor; |
| |
| protected RadLayoutManager myLayoutManager; |
| private LayoutManager myDelegeeLayout; |
| |
| public RadContainer(final ModuleProvider module, final String id) { |
| this(module, JPanel.class, id); |
| } |
| |
| public RadContainer(final ModuleProvider module, final Class aClass, final String id) { |
| super(module, aClass, id); |
| |
| myComponents = new ArrayList<RadComponent>(); |
| |
| // By default container doesn't have any special border |
| setBorderType(BorderType.NONE); |
| |
| myLayoutManager = createInitialLayoutManager(); |
| if (myLayoutManager != null) { |
| final LayoutManager layoutManager = myLayoutManager.createLayout(); |
| if (layoutManager != null) { |
| setLayout(layoutManager); |
| } |
| } |
| } |
| |
| public RadContainer(@NotNull final Class aClass, @NotNull final String id, final Palette palette) { |
| this(null, aClass, id); |
| setPalette(palette); |
| } |
| |
| @Nullable |
| protected RadLayoutManager createInitialLayoutManager() { |
| String defaultLayoutManager = UIFormXmlConstants.LAYOUT_INTELLIJ; |
| if (getModule() != null) { |
| final GuiDesignerConfiguration configuration = GuiDesignerConfiguration.getInstance(getProject()); |
| defaultLayoutManager = configuration.DEFAULT_LAYOUT_MANAGER; |
| } |
| |
| try { |
| return LayoutManagerRegistry.createLayoutManager(defaultLayoutManager); |
| } |
| catch (Exception e) { |
| LOG.error(e); |
| return new RadGridLayoutManager(); |
| } |
| } |
| |
| public Property getInplaceProperty(final int x, final int y) { |
| // 1. We have to check whether user clicked inside border (if any) or not. |
| // In this case we have return inplace editor for border text |
| final Insets insets = getDelegee().getInsets(); // border insets |
| if ( |
| x < insets.left || x > getWidth() - insets.right || |
| y < 0 || y > insets.top |
| ) { |
| return super.getInplaceProperty(x, y); |
| } |
| |
| // 2. Now we are sure that user clicked inside title area |
| return new MyBorderTitleProperty(); |
| } |
| |
| @Override |
| @Nullable |
| public Property getDefaultInplaceProperty() { |
| return new MyBorderTitleProperty(); |
| } |
| |
| @Override |
| @Nullable |
| public Rectangle getDefaultInplaceEditorBounds() { |
| return getBorderInPlaceEditorBounds(new MyBorderTitleProperty()); |
| } |
| |
| public Rectangle getInplaceEditorBounds(final Property property, final int x, final int y) { |
| if (property instanceof MyBorderTitleProperty) { // If this is our property |
| return getBorderInPlaceEditorBounds(property); |
| } |
| return super.getInplaceEditorBounds(property, x, y); |
| } |
| |
| private Rectangle getBorderInPlaceEditorBounds(final Property property) { |
| final MyBorderTitleProperty _property = (MyBorderTitleProperty)property; |
| final Insets insets = getDelegee().getInsets(); |
| return new Rectangle( |
| insets.left, |
| 0, |
| getWidth() - insets.left - insets.right, |
| _property.getPreferredSize().height |
| ); |
| } |
| |
| public final LayoutManager getLayout() { |
| if (myDelegeeLayout != null) { |
| return myDelegeeLayout; |
| } |
| return getDelegee().getLayout(); |
| } |
| |
| public final void setLayout(final LayoutManager layout) { |
| // some components (for example, JXCollapsiblePanel from SwingX) have asymmetrical getLayout/setLayout - a different |
| // layout is returned compared to what was passed to setLayout(). to avoid crashes, we store the layout we passed to |
| // the component. |
| myDelegeeLayout = layout; |
| getDelegee().setLayout(layout); |
| |
| if (layout instanceof AbstractLayout) { |
| AbstractLayout aLayout = (AbstractLayout)layout; |
| for (int i = 0; i < getComponentCount(); i++) { |
| final RadComponent c = getComponent(i); |
| aLayout.addLayoutComponent(c.getDelegee(), c.getConstraints()); |
| } |
| } |
| } |
| |
| public final boolean isXY() { |
| return getLayout() instanceof XYLayoutManager; |
| } |
| |
| /** |
| * @param component component to be added. |
| * @throws java.lang.IllegalArgumentException |
| * if <code>component</code> is <code>null</code> |
| * @throws java.lang.IllegalArgumentException |
| * if <code>component</code> already exist in the |
| * container |
| */ |
| public final void addComponent(@NotNull final RadComponent component, int index) { |
| if (myComponents.contains(component)) { |
| //noinspection HardCodedStringLiteral |
| throw new IllegalArgumentException("component is already added: " + component); |
| } |
| |
| final RadComponent[] oldChildren = myComponents.toArray(new RadComponent[myComponents.size()]); |
| |
| // Remove from old parent |
| final RadContainer oldParent = component.getParent(); |
| if (oldParent != null) { |
| oldParent.removeComponent(component); |
| } |
| |
| // Attach to new parent |
| myComponents.add(index, component); |
| component.setParent(this); |
| myLayoutManager.addComponentToContainer(this, component, index); |
| |
| final RadComponent[] newChildren = myComponents.toArray(new RadComponent[myComponents.size()]); |
| firePropertyChanged(PROP_CHILDREN, oldChildren, newChildren); |
| } |
| |
| public final void addComponent(@NotNull final RadComponent component) { |
| addComponent(component, myComponents.size()); |
| } |
| |
| /** |
| * Removes specified <code>component</code> from the container. |
| * This method also removes component's delegee from the |
| * container's delegee. Client code is responsible for revalidation |
| * of invalid Swing hierarchy. |
| * |
| * @param component component to be removed. |
| * @throws java.lang.IllegalArgumentException |
| * if <code>component</code> |
| * is <code>null</code> |
| * @throws java.lang.IllegalArgumentException |
| * if <code>component</code> |
| * doesn't exist in the container |
| */ |
| public final void removeComponent(@NotNull final RadComponent component) { |
| if (!myComponents.contains(component)) { |
| //noinspection HardCodedStringLiteral |
| throw new IllegalArgumentException("component is not added: " + component); |
| } |
| |
| final RadComponent[] oldChildren = myComponents.toArray(new RadComponent[myComponents.size()]); |
| |
| // Remove child |
| component.setParent(null); |
| myComponents.remove(component); |
| myLayoutManager.removeComponentFromContainer(this, component); |
| |
| final RadComponent[] newChildren = myComponents.toArray(new RadComponent[myComponents.size()]); |
| firePropertyChanged(PROP_CHILDREN, oldChildren, newChildren); |
| } |
| |
| public final RadComponent getComponent(final int index) { |
| return myComponents.get(index); |
| } |
| |
| public final int getComponentCount() { |
| return myComponents.size(); |
| } |
| |
| public int indexOfComponent(IComponent component) { |
| return myComponents.indexOf(component); |
| } |
| |
| /** |
| * @return new array with all children |
| */ |
| public final RadComponent[] getComponents() { |
| return myComponents.toArray(new RadComponent[myComponents.size()]); |
| } |
| |
| @NotNull |
| public ComponentDropLocation getDropLocation(@Nullable Point location) { |
| return getLayoutManager().getDropLocation(this, location); |
| } |
| |
| public RadComponent findComponentInRect(final int startRow, final int startCol, final int rowSpan, final int colSpan) { |
| for (int r = startRow; r < startRow + rowSpan; r++) { |
| for (int c = startCol; c < startCol + colSpan; c++) { |
| final RadComponent result = getComponentAtGrid(r, c); |
| if (result != null) { |
| return result; |
| } |
| } |
| } |
| return null; |
| } |
| |
| @Nullable |
| public RadComponent getComponentAtGrid(boolean rowFirst, int coord1, int coord2) { |
| return rowFirst ? getComponentAtGrid(coord1, coord2) : getComponentAtGrid(coord2, coord1); |
| } |
| |
| @Nullable |
| public RadComponent getComponentAtGrid(int row, int col) { |
| return getGridLayoutManager().getComponentAtGrid(this, row, col); |
| } |
| |
| public int getGridRowCount() { |
| return getGridLayoutManager().getGridRowCount(this); |
| } |
| |
| public int getGridColumnCount() { |
| return getGridLayoutManager().getGridColumnCount(this); |
| } |
| |
| public int getGridCellCount(boolean isRow) { |
| return isRow ? getGridRowCount() : getGridColumnCount(); |
| } |
| |
| public int getGridRowAt(int y) { |
| return getGridLayoutManager().getGridRowAt(this, y); |
| } |
| |
| public int getGridColumnAt(int x) { |
| return getGridLayoutManager().getGridColumnAt(this, x); |
| } |
| |
| /** |
| * @return border's type. |
| * @see com.intellij.uiDesigner.shared.BorderType |
| */ |
| @NotNull |
| public final BorderType getBorderType() { |
| return myBorderType; |
| } |
| |
| /** |
| * @throws java.lang.IllegalArgumentException |
| * if <code>type</code> |
| * is <code>null</code> |
| * @see com.intellij.uiDesigner.shared.BorderType |
| */ |
| public final void setBorderType(@NotNull final BorderType type) { |
| if (myBorderType == type) { |
| return; |
| } |
| myBorderType = type; |
| updateBorder(); |
| } |
| |
| /** |
| * @return border's title. If the container doesn't have any title then the |
| * method returns <code>null</code>. |
| */ |
| @Nullable |
| public final StringDescriptor getBorderTitle() { |
| return myBorderTitle; |
| } |
| |
| /** |
| * @param title new border's title. <code>null</code> means that |
| * the containr doesn't have have titled border. |
| */ |
| public final void setBorderTitle(final StringDescriptor title) { |
| if (Comparing.equal(title, myBorderTitle)) { |
| return; |
| } |
| myBorderTitle = title; |
| updateBorder(); |
| } |
| |
| public int getBorderTitleJustification() { |
| return myBorderTitleJustification; |
| } |
| |
| public void setBorderTitleJustification(final int borderTitleJustification) { |
| if (myBorderTitleJustification != borderTitleJustification) { |
| myBorderTitleJustification = borderTitleJustification; |
| updateBorder(); |
| } |
| } |
| |
| public int getBorderTitlePosition() { |
| return myBorderTitlePosition; |
| } |
| |
| public void setBorderTitlePosition(final int borderTitlePosition) { |
| if (myBorderTitlePosition != borderTitlePosition) { |
| myBorderTitlePosition = borderTitlePosition; |
| updateBorder(); |
| } |
| } |
| |
| public FontDescriptor getBorderTitleFont() { |
| return myBorderTitleFont; |
| } |
| |
| public void setBorderTitleFont(final FontDescriptor borderTitleFont) { |
| if (!Comparing.equal(myBorderTitleFont, borderTitleFont)) { |
| myBorderTitleFont = borderTitleFont; |
| updateBorder(); |
| } |
| } |
| |
| public ColorDescriptor getBorderTitleColor() { |
| return myBorderTitleColor; |
| } |
| |
| public void setBorderTitleColor(final ColorDescriptor borderTitleColor) { |
| if (!Comparing.equal(myBorderTitleColor, borderTitleColor)) { |
| myBorderTitleColor = borderTitleColor; |
| updateBorder(); |
| } |
| } |
| |
| public Insets getBorderSize() { |
| return myBorderSize; |
| } |
| |
| public void setBorderSize(final Insets borderSize) { |
| if (!Comparing.equal(myBorderSize, borderSize)) { |
| myBorderSize = borderSize; |
| updateBorder(); |
| } |
| } |
| |
| public ColorDescriptor getBorderColor() { |
| return myBorderColor; |
| } |
| |
| public void setBorderColor(final ColorDescriptor borderColor) { |
| if (!Comparing.equal(myBorderColor, borderColor)) { |
| myBorderColor = borderColor; |
| updateBorder(); |
| } |
| } |
| |
| /** |
| * Updates delegee's border |
| */ |
| public boolean updateBorder() { |
| String title = null; |
| String oldTitle = null; |
| if (myBorderTitle != null) { |
| oldTitle = myBorderTitle.getResolvedValue(); |
| myBorderTitle.setResolvedValue(null); |
| // NOTE: the explicit getValue() check is required for SnapShooter operation |
| if (myBorderTitle.getValue() != null) { |
| title = myBorderTitle.getValue(); |
| } |
| else { |
| title = StringDescriptorManager.getInstance(getModule()).resolve(this, myBorderTitle); |
| } |
| } |
| Font font = (myBorderTitleFont != null) ? myBorderTitleFont.getResolvedFont(getDelegee().getFont()) : null; |
| Color titleColor = (myBorderTitleColor != null) ? myBorderTitleColor.getResolvedColor() : null; |
| Color borderColor = (myBorderColor != null) ? myBorderColor.getResolvedColor() : null; |
| getDelegee().setBorder(myBorderType.createBorder(title, myBorderTitleJustification, myBorderTitlePosition, |
| font, titleColor, myBorderSize, borderColor)); |
| return myBorderTitle != null && !Comparing.equal(oldTitle, myBorderTitle.getResolvedValue()); |
| } |
| |
| public RadLayoutManager getLayoutManager() { |
| RadContainer parent = this; |
| while (parent != null) { |
| if (parent.myLayoutManager != null) { |
| return parent.myLayoutManager; |
| } |
| parent = parent.getParent(); |
| } |
| return null; |
| } |
| |
| public void setLayoutManager(final RadLayoutManager layoutManager) { |
| myLayoutManager = layoutManager; |
| setLayout(myLayoutManager.createLayout()); |
| } |
| |
| public void setLayoutManager(RadLayoutManager layoutManager, LayoutManager layout) { |
| myLayoutManager = layoutManager; |
| setLayout(layout); |
| } |
| |
| public RadComponent getActionTargetComponent(RadComponent child) { |
| return child; |
| } |
| |
| @Override |
| public boolean areChildrenExclusive() { |
| return myLayoutManager.areChildrenExclusive(); |
| } |
| |
| @Override |
| public void refresh() { |
| for (int i = 0; i < getComponentCount(); i++) { |
| getComponent(i).refresh(); |
| } |
| myLayoutManager.refresh(this); |
| } |
| |
| /** |
| * Serializes container's border |
| */ |
| protected final void writeBorder(final XmlWriter writer) { |
| writer.startElement(UIFormXmlConstants.ELEMENT_BORDER); |
| try { |
| writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_TYPE, getBorderType().getId()); |
| if (getBorderTitle() != null) { |
| final StringDescriptor descriptor = getBorderTitle(); |
| writer.writeStringDescriptor(descriptor, UIFormXmlConstants.ATTRIBUTE_TITLE, |
| UIFormXmlConstants.ATTRIBUTE_TITLE_RESOURCE_BUNDLE, |
| UIFormXmlConstants.ATTRIBUTE_TITLE_KEY); |
| } |
| if (myBorderTitleJustification != 0) { |
| writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_TITLE_JUSTIFICATION, myBorderTitleJustification); |
| } |
| if (myBorderTitlePosition != 0) { |
| writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_TITLE_POSITION, myBorderTitlePosition); |
| } |
| if (myBorderTitleFont != null) { |
| writer.startElement(UIFormXmlConstants.ELEMENT_FONT); |
| writer.writeFontDescriptor(myBorderTitleFont); |
| writer.endElement(); |
| } |
| if (myBorderTitleColor != null) { |
| writer.startElement(UIFormXmlConstants.ELEMENT_TITLE_COLOR); |
| writer.writeColorDescriptor(myBorderTitleColor); |
| writer.endElement(); |
| } |
| if (myBorderSize != null) { |
| writer.startElement(UIFormXmlConstants.ELEMENT_SIZE); |
| writer.writeInsets(myBorderSize); |
| writer.endElement(); |
| } |
| if (myBorderColor != null) { |
| writer.startElement(UIFormXmlConstants.ELEMENT_COLOR); |
| writer.writeColorDescriptor(myBorderColor); |
| writer.endElement(); |
| } |
| } |
| finally { |
| writer.endElement(); // border |
| } |
| } |
| |
| /** |
| * Serializes container's children |
| */ |
| protected final void writeChildren(final XmlWriter writer) { |
| // Children |
| writer.startElement("children"); |
| try { |
| writeChildrenImpl(writer); |
| } |
| finally { |
| writer.endElement(); // children |
| } |
| } |
| |
| protected final void writeChildrenImpl(final XmlWriter writer) { |
| for (int i = 0; i < getComponentCount(); i++) { |
| getComponent(i).write(writer); |
| } |
| } |
| |
| public void write(final XmlWriter writer) { |
| if (isXY()) { |
| writer.startElement("xy"); |
| } |
| else { |
| writer.startElement("grid"); |
| } |
| try { |
| writeId(writer); |
| writeClassIfDifferent(writer, JPanel.class.getName()); |
| writeBinding(writer); |
| |
| if (myLayoutManager != null) { |
| writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_LAYOUT_MANAGER, myLayoutManager.getName()); |
| } |
| |
| getLayoutManager().writeLayout(writer, this); |
| |
| // Constraints and properties |
| writeConstraints(writer); |
| writeProperties(writer); |
| |
| // Border |
| writeBorder(writer); |
| |
| // Children |
| writeChildren(writer); |
| } |
| finally { |
| writer.endElement(); // xy/grid |
| } |
| } |
| |
| public boolean accept(ComponentVisitor visitor) { |
| if (!super.accept(visitor)) { |
| return false; |
| } |
| |
| for (int i = 0; i < getComponentCount(); i++) { |
| final IComponent c = getComponent(i); |
| if (!c.accept(visitor)) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| protected void writeNoLayout(final XmlWriter writer, final String defaultClassName) { |
| writeId(writer); |
| writeClassIfDifferent(writer, defaultClassName); |
| writeBinding(writer); |
| |
| // Constraints and properties |
| writeConstraints(writer); |
| writeProperties(writer); |
| |
| // Margin and border |
| writeBorder(writer); |
| writeChildren(writer); |
| } |
| |
| @Override |
| protected void importSnapshotComponent(final SnapshotContext context, final JComponent component) { |
| getLayoutManager().createSnapshotLayout(context, component, this, component.getLayout()); |
| importSnapshotBorder(component); |
| for (Component child : component.getComponents()) { |
| if (child instanceof JComponent) { |
| RadComponent childComponent = createSnapshotComponent(context, (JComponent)child); |
| if (childComponent != null) { |
| getLayoutManager().addSnapshotComponent(component, (JComponent)child, this, childComponent); |
| } |
| } |
| } |
| } |
| |
| private void importSnapshotBorder(final JComponent component) { |
| Border border = component.getBorder(); |
| if (border != null) { |
| if (border instanceof TitledBorder) { |
| TitledBorder titledBorder = (TitledBorder)border; |
| setBorderTitle(StringDescriptor.create(titledBorder.getTitle())); |
| setBorderTitleJustification(titledBorder.getTitleJustification()); |
| setBorderTitlePosition(titledBorder.getTitlePosition()); |
| final Font titleFont = titledBorder.getTitleFont(); |
| setBorderTitleFont(new FontDescriptor(titleFont.getName(), titleFont.getStyle(), titleFont.getSize())); |
| setBorderTitleColor(new ColorDescriptor(titledBorder.getTitleColor())); |
| border = titledBorder.getBorder(); |
| } |
| |
| if (border instanceof EtchedBorder) { |
| setBorderType(BorderType.ETCHED); |
| } |
| else if (border instanceof BevelBorder) { |
| BevelBorder bevelBorder = (BevelBorder)border; |
| setBorderType(bevelBorder.getBevelType() == BevelBorder.RAISED ? BorderType.BEVEL_RAISED : BorderType.BEVEL_LOWERED); |
| } |
| else if (border instanceof EmptyBorder) { |
| EmptyBorder emptyBorder = (EmptyBorder)border; |
| setBorderType(BorderType.EMPTY); |
| setBorderSize(emptyBorder.getBorderInsets()); |
| } |
| else if (border instanceof LineBorder) { |
| LineBorder lineBorder = (LineBorder)border; |
| setBorderType(BorderType.LINE); |
| setBorderColor(new ColorDescriptor(lineBorder.getLineColor())); |
| } |
| } |
| } |
| |
| public RadAbstractGridLayoutManager getGridLayoutManager() { |
| if (!(myLayoutManager instanceof RadAbstractGridLayoutManager)) { |
| throw new RuntimeException("Not a grid container: " + myLayoutManager); |
| } |
| return (RadAbstractGridLayoutManager)myLayoutManager; |
| } |
| |
| @Nullable |
| public RadComponent findComponentWithConstraints(final Object constraints) { |
| for (RadComponent component : getComponents()) { |
| if (constraints.equals(component.getCustomLayoutConstraints())) { |
| return component; |
| } |
| } |
| return null; |
| } |
| |
| private final class MyBorderTitleProperty extends Property<RadContainer, StringDescriptor> { |
| private final StringEditor myEditor; |
| |
| public MyBorderTitleProperty() { |
| super(null, "Title"); |
| myEditor = new StringEditor(getProject()); |
| } |
| |
| public Dimension getPreferredSize() { |
| return myEditor.getPreferredSize(); |
| } |
| |
| public StringDescriptor getValue(final RadContainer component) { |
| return myBorderTitle; |
| } |
| |
| protected void setValueImpl(final RadContainer container, final StringDescriptor value) throws Exception { |
| setBorderTitle(value); |
| } |
| |
| @NotNull |
| public PropertyRenderer<StringDescriptor> getRenderer() { |
| return null; |
| } |
| |
| public PropertyEditor<StringDescriptor> getEditor() { |
| return myEditor; |
| } |
| } |
| } |