2 * Copyright (c) 2005 Your Corporation. All Rights Reserved.
4 package com
.intellij
.util
.xml
.ui
;
6 import com
.intellij
.j2ee
.j2eeDom
.xmlData
.ReadOnlyDeploymentDescriptorModificationException
;
7 import com
.intellij
.javaee
.ui
.Warning
;
8 import com
.intellij
.openapi
.actionSystem
.AnAction
;
9 import com
.intellij
.openapi
.actionSystem
.AnActionEvent
;
10 import com
.intellij
.openapi
.application
.ApplicationManager
;
11 import com
.intellij
.openapi
.application
.Result
;
12 import com
.intellij
.openapi
.command
.WriteCommandAction
;
13 import com
.intellij
.openapi
.project
.Project
;
14 import com
.intellij
.openapi
.util
.Comparing
;
15 import com
.intellij
.util
.Consumer
;
16 import com
.intellij
.util
.EventDispatcher
;
17 import com
.intellij
.util
.ui
.ColumnInfo
;
18 import com
.intellij
.util
.xml
.DomElement
;
19 import com
.intellij
.util
.xml
.DomUtil
;
20 import com
.intellij
.util
.xml
.reflect
.DomCollectionChildDescription
;
21 import com
.intellij
.util
.xml
.ui
.actions
.DefaultAddAction
;
22 import org
.jetbrains
.annotations
.NonNls
;
23 import org
.jetbrains
.annotations
.Nullable
;
26 import javax
.swing
.table
.*;
28 import java
.util
.ArrayList
;
29 import java
.util
.Collections
;
30 import java
.util
.List
;
35 public class DomCollectionControl
<T
extends DomElement
> implements DomUIControl
{
36 private final EventDispatcher
<CommitListener
> myDispatcher
= EventDispatcher
.create(CommitListener
.class);
37 protected DomCollectionPanel myCollectionPanel
;
39 private final List
<T
> myData
= new ArrayList
<T
>();
40 private final DomElement myParentDomElement
;
41 private final DomCollectionChildDescription myChildDescription
;
42 private ColumnInfo
<T
, ?
>[] myColumnInfos
;
43 private boolean myEditable
= false;
45 public DomCollectionControl(DomElement parentElement
,
46 DomCollectionChildDescription description
,
47 final boolean editable
,
48 ColumnInfo
<T
, ?
>... columnInfos
) {
49 myChildDescription
= description
;
50 myParentDomElement
= parentElement
;
51 myColumnInfos
= columnInfos
;
52 myEditable
= editable
;
55 public DomCollectionControl(DomElement parentElement
,
56 @NonNls String subTagName
,
57 final boolean editable
,
58 ColumnInfo
<T
, ?
>... columnInfos
) {
59 this(parentElement
, parentElement
.getGenericInfo().getCollectionChildDescription(subTagName
), editable
, columnInfos
);
62 public DomCollectionControl(DomElement parentElement
, DomCollectionChildDescription description
) {
63 myChildDescription
= description
;
64 myParentDomElement
= parentElement
;
67 public DomCollectionControl(DomElement parentElement
, @NonNls String subTagName
) {
68 this(parentElement
, parentElement
.getGenericInfo().getCollectionChildDescription(subTagName
));
71 public boolean isEditable() {
75 public final ColumnInfo
<T
, ?
>[] getColumnInfos() {
79 public void bind(JComponent component
) {
80 assert component
instanceof DomCollectionPanel
;
82 initialize((DomCollectionPanel
)component
);
85 public void addCommitListener(CommitListener listener
) {
86 myDispatcher
.addListener(listener
);
89 public void removeCommitListener(CommitListener listener
) {
90 myDispatcher
.removeListener(listener
);
94 public boolean canNavigate(DomElement element
) {
95 final Class
<DomElement
> aClass
= (Class
<DomElement
>)DomUtil
.getRawType(myChildDescription
.getType());
97 final DomElement domElement
= element
.getParentOfType(aClass
, false);
99 return domElement
!= null && myData
.contains(domElement
);
102 public void navigate(DomElement element
) {
103 final Class
<DomElement
> aClass
= (Class
<DomElement
>)DomUtil
.getRawType(myChildDescription
.getType());
104 final DomElement domElement
= element
.getParentOfType(aClass
, false);
106 int index
= myData
.indexOf(domElement
);
107 if (index
< 0) index
= 0;
109 myCollectionPanel
.getTable().setRowSelectionInterval(index
, index
);
112 protected void initialize(final DomCollectionPanel boundComponent
) {
113 if (boundComponent
== null) {
114 myCollectionPanel
= new DomCollectionPanel();
117 myCollectionPanel
= boundComponent
;
119 myCollectionPanel
.setControl(this);
120 myColumnInfos
= createColumnInfos(myParentDomElement
);
126 protected ColumnInfo
[] createColumnInfos(DomElement parent
) {
127 return myColumnInfos
;
130 protected void initializeTable() {
131 JTable table
= myCollectionPanel
.getTable();
133 myCollectionPanel
.setTableModel(new AbstractTableModel() {
134 public int getRowCount() {
135 return myData
.size();
138 public int getColumnCount() {
139 return myColumnInfos
.length
;
142 public boolean isCellEditable(int rowIndex
, int columnIndex
) {
143 return myColumnInfos
[columnIndex
].isCellEditable(myData
.get(rowIndex
));
146 public String
getColumnName(int column
) {
147 return myColumnInfos
[column
].getName();
150 public Class
getColumnClass(int columnIndex
) {
151 return myColumnInfos
[columnIndex
].getColumnClass();
154 public void setValueAt(final Object aValue
, final int rowIndex
, final int columnIndex
) {
155 final Object oldValue
= getValueAt(rowIndex
, columnIndex
);
156 if (!Comparing
.equal(oldValue
, aValue
)) {
157 performWriteCommandAction(new WriteCommandAction(getProject()) {
158 protected void run(final Result result
) throws Throwable
{
159 ((ColumnInfo
<T
, Object
>)myColumnInfos
[columnIndex
]).setValue(myData
.get(rowIndex
), aValue
);
165 public Object
getValueAt(int rowIndex
, int columnIndex
) {
166 return myColumnInfos
[columnIndex
].valueOf(myData
.get(rowIndex
));
170 adjustColumnWidths(table
);
174 private void adjustColumnWidths(final JTable table
) {
175 for (int i
= 0; i
< myColumnInfos
.length
; i
++) {
176 ColumnInfo
<T
, ?
> columnInfo
= myColumnInfos
[i
];
177 final TableColumn column
= table
.getColumnModel().getColumn(i
);
178 final TableCellRenderer cellRenderer
= columnInfo
.getRenderer(null);
179 if (cellRenderer
!= null) {
180 column
.setCellRenderer(cellRenderer
);
183 for (int j
= 0; j
< myData
.size(); j
++) {
185 final Component component
= cellRenderer
.getTableCellRendererComponent(table
, columnInfo
.valueOf(t
), false, false, j
, i
);
186 final int prefWidth
= component
.getPreferredSize().width
;
187 if (prefWidth
> width
) {
192 column
.setPreferredWidth(width
);
195 final TableCellEditor cellEditor
= columnInfo
.getEditor(null);
196 if (cellEditor
!= null) {
197 column
.setCellEditor(cellEditor
);
202 public final void columnsChanged() {
203 myColumnInfos
= createColumnInfos(myParentDomElement
);
204 final JTable table
= myCollectionPanel
.getTable();
205 ((AbstractTableModel
)table
.getModel()).fireTableStructureChanged();
206 adjustColumnWidths(table
);
209 protected void doEdit() {
210 doEdit(myData
.get(myCollectionPanel
.getTable().getSelectedRow()));
213 protected void doEdit(final T t
) {
214 final DomEditorManager manager
= getDomEditorManager(this);
215 if (manager
!= null) {
216 manager
.openDomElementEditor(t
);
220 protected void removeInternal(final Consumer
<T
> consumer
, final List
<T
> toDelete
) {
221 new WriteCommandAction(getProject()) {
222 protected void run(Result result
) throws Throwable
{
223 for (final T t
: toDelete
) {
230 protected void doRemove() {
231 ApplicationManager
.getApplication().invokeLater(new Runnable() {
233 final int[] selected
= myCollectionPanel
.getTable().getSelectedRows();
234 if (selected
== null || selected
.length
== 0) return;
235 List
<T
> selectedElements
= new ArrayList
<T
>(selected
.length
);
236 for (final int i
: selected
) {
237 selectedElements
.add(myData
.get(i
));
239 removeInternal(new Consumer
<T
>() {
240 public void consume(final T t
) {
246 }, selectedElements
);
248 myCollectionPanel
.getTableModel().fireTableDataChanged();
249 int selection
= selected
[0];
250 if (selection
>= myData
.size()) {
251 selection
= myData
.size() - 1;
253 if (selection
>= 0) {
254 myCollectionPanel
.getTable().setRowSelectionInterval(selection
, selection
);
260 protected static void performWriteCommandAction(final WriteCommandAction writeCommandAction
) {
261 writeCommandAction
.execute();
264 public void commit() throws ReadOnlyDeploymentDescriptorModificationException
{
265 final CommitListener listener
= myDispatcher
.getMulticaster();
266 listener
.beforeCommit(this);
267 listener
.afterCommit(this);
270 public void dispose() {
271 if (myCollectionPanel
!= null) {
272 myCollectionPanel
.dispose();
276 protected final Project
getProject() {
277 return myParentDomElement
.getManager().getProject();
280 public JComponent
getFocusedComponent() {
281 return getBoundComponent();
284 public JComponent
getBoundComponent() {
285 return getComponent();
288 public JComponent
getComponent() {
289 if (myCollectionPanel
== null) initialize(null);
291 return myCollectionPanel
;
294 public final DomCollectionChildDescription
getChildDescription() {
295 return myChildDescription
;
298 public final List
<?
extends T
> getCollectionElements() {
299 return (List
<?
extends T
>)myChildDescription
.getValues(myParentDomElement
);
302 public final DomElement
getDomElement() {
303 return myParentDomElement
;
306 public List
<Warning
> getWarnings() {
307 return Collections
.emptyList();
310 public final void reset() {
312 myData
.addAll(getData());
313 if (myCollectionPanel
!= null) {
318 private void fireTableChanged() {
319 final int row
= myCollectionPanel
.getTable().getSelectedRow();
320 myCollectionPanel
.getTableModel().fireTableDataChanged();
321 if (row
>= 0 && row
< myData
.size()) {
322 myCollectionPanel
.getTable().getSelectionModel().setSelectionInterval(row
, row
);
326 public List
<T
> getData() {
327 return (List
<T
>)myChildDescription
.getValues(myParentDomElement
);
331 protected AnAction
[] createAdditionActions() {
335 protected DefaultAddAction
createDefaultAction(final String name
, final Icon icon
, final Class s
) {
336 return new ControlAddAction(name
, "", icon
) {
337 protected Class
getElementClass() {
343 protected final Class
<?
extends T
> getCollectionElementClass() {
344 return (Class
<?
extends T
>)DomUtil
.getRawType(myChildDescription
.getType());
349 private static DomEditorManager
getDomEditorManager(DomUIControl control
) {
350 JComponent component
= control
.getComponent();
351 while (component
!= null && !(component
instanceof DomEditorManager
)) {
352 final Container parent
= component
.getParent();
353 if (!(parent
instanceof JComponent
)) {
356 component
= (JComponent
)parent
;
358 return (DomEditorManager
)component
;
361 public class ControlAddAction
extends DefaultAddAction
<T
> {
363 public ControlAddAction() {
366 public ControlAddAction(final String text
) {
370 public ControlAddAction(final String text
, final String description
, final Icon icon
) {
371 super(text
, description
, icon
);
374 protected final DomCollectionChildDescription
getDomCollectionChildDescription() {
375 return myChildDescription
;
378 protected final DomElement
getParentDomElement() {
379 return myParentDomElement
;
382 protected void afterAddition(final JTable table
, final int rowIndex
) {
383 table
.setRowSelectionInterval(rowIndex
, rowIndex
);
386 protected final void afterAddition(final AnActionEvent e
, final DomElement newElement
) {
387 if (newElement
!= null) {
389 afterAddition(myCollectionPanel
.getTable(), myData
.size() - 1);