001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2002-2005 Julian Hyde
008// Copyright (C) 2005-2009 Pentaho and others
009// Copyright (C) 2006-2007 CINCOM SYSTEMS, INC.
010// All Rights Reserved.
011*/
012package mondrian.gui;
013
014import java.awt.*;
015import java.io.StringReader;
016import javax.swing.*;
017import javax.swing.border.EmptyBorder;
018import javax.swing.table.TableCellRenderer;
019
020/**
021 * @author sean
022 */
023public class SchemaPropertyCellRenderer
024    extends javax.swing.table.DefaultTableCellRenderer
025{
026    Workbench workbench;
027
028    JLabel stringRenderer;
029    JCheckBox booleanRenderer;
030    JLabel integerRenderer;
031    JTable tableRenderer;
032    JComboBox listRenderer;
033
034    JScrollPane jScrollPaneCDATA;
035    // JEditorPane jEditorPaneCDATA;
036    JTextArea cdataTextArea;
037
038    JComboBox relationList;  // Join, Table
039    JTable relationTable;
040    JPanel relationRenderer, rlPanel;
041
042    JScrollPane jScrollPaneT;
043
044    // All objects of this class will use this color value to render attribute
045    // column this value is initialized by SchemaExplorer to the scrollpane
046    // background color value.
047    public static Color attributeBackground;
048
049    /**
050     * Creates a new instance of SchemaPropertyCellRenderer
051     */
052    public SchemaPropertyCellRenderer(Workbench wb) {
053        workbench = wb;
054
055        super.setBackground(attributeBackground);
056
057        stringRenderer = new JLabel();
058        stringRenderer.setFont(Font.decode("Dialog"));
059
060        // cdata multi-line
061
062        cdataTextArea = new JTextArea();
063        cdataTextArea.setLineWrap(true);
064        cdataTextArea.setWrapStyleWord(true);
065        cdataTextArea.setLayout(new java.awt.BorderLayout());
066        cdataTextArea.setEditable(true);
067        cdataTextArea.setPreferredSize(new java.awt.Dimension(100, 300));
068        cdataTextArea.setMinimumSize(new java.awt.Dimension(100, 100));
069
070        jScrollPaneCDATA = new JScrollPane(cdataTextArea);
071        jScrollPaneCDATA.setMaximumSize(cdataTextArea.getPreferredSize());
072
073        booleanRenderer = new JCheckBox();
074        booleanRenderer.setBackground(Color.white);
075        integerRenderer = new JLabel();
076        integerRenderer.setHorizontalAlignment(JTextField.RIGHT);
077        integerRenderer.setFont(Font.decode("Courier"));
078
079
080        listRenderer = new JComboBox(MondrianGuiDef.Measure._aggregator_values);
081        listRenderer.setMaximumSize(stringRenderer.getMaximumSize());
082        listRenderer.setFont(Font.decode("Dialog"));
083        listRenderer.setBackground(Color.white);
084        //listRenderer.setModel(new ComboBoxModel());
085        listRenderer.setBorder(
086            new EmptyBorder(
087                0, 0, 0, 0)); //super.noFocusBorder);
088        listRenderer.setRenderer(new ListRenderer(listRenderer.getRenderer()));
089
090        /*
091        relationListRenderer = new JComboBox(new String[] {"Join", "Table"});
092        relationListRenderer.setMaximumSize(stringRenderer.getMaximumSize());
093        relationListRenderer.setFont(Font.decode("Dialog"));
094        relationListRenderer.setBackground(Color.white);
095         */
096        relationRenderer = new JPanel();
097
098        rlPanel = new JPanel();
099        relationList = new JComboBox(
100            new String[]{
101                workbench.getResourceConverter().getString(
102                    "schemaPropertyCellRenderer.join", "Join"),
103                workbench.getResourceConverter().getString(
104                    "schemaPropertyCellRenderer.table", "Table")
105            });
106        relationList.setMaximumSize(new Dimension(55, 22));
107        relationList.setPreferredSize(new Dimension(55, 22));
108        relationList.setMinimumSize(new Dimension(55, 22));
109        relationList.setFont(Font.decode("Dialog"));
110        relationList.setBackground(Color.white);
111
112        relationTable = new JTable();
113        relationTable.setBackground(new java.awt.Color(255, 204, 204));
114
115        // to remove table headers 'Property', 'Value''
116        relationTable.setTableHeader(null);
117
118        jScrollPaneT = new JScrollPane();
119        jScrollPaneT.setViewportBorder(
120            javax.swing.BorderFactory.createLineBorder(
121                new java.awt.Color(
122                    255, 0, 255), 2));
123        jScrollPaneT.setVerticalScrollBarPolicy(
124            ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
125        jScrollPaneT.setViewportView(relationTable);
126
127        relationRenderer.setLayout(new BorderLayout());
128        rlPanel.add(relationList);
129        relationRenderer.add(rlPanel, java.awt.BorderLayout.WEST);
130        relationRenderer.add(jScrollPaneT, java.awt.BorderLayout.CENTER);
131
132
133        relationRenderer.setBackground(Color.white);
134
135        //relationRenderer.add(jScrollPaneT,java.awt.BorderLayout.CENTER);
136
137        //JPanel relPanel = new JPanel();  // default flowlayout
138        //relPanel.add(relationList);
139        //relPanel.add(jScrollPaneT);
140        //relationRenderer.add(relationTable);
141        //relationRenderer.add(relPanel,java.awt.BorderLayout.CENTER);
142        //relationRenderer.add(jScrollPaneT);
143
144        tableRenderer = new JTable();
145    }
146
147    public JCheckBox getBooleanRenderer() {
148        return booleanRenderer;
149    }
150
151    public Component getTableCellRendererComponent(
152        JTable table,
153        Object value,
154        boolean isSelected,
155        boolean hasFocus,
156        int row,
157        int column)
158    {
159        if (column == 1) {
160            PropertyTableModel tableModel =
161                (PropertyTableModel) table.getModel();
162            Class targetClassz = tableModel.target.getClass();
163            String propertyName = tableModel.getRowName(row);
164
165            stringRenderer.setOpaque(false);
166            stringRenderer.setToolTipText(null);
167            stringRenderer.setBackground(Color.white);
168
169            //targetClassz == MondrianGuiDef.Formula.class &&
170            if (propertyName.equals("cdata")) {
171                try {
172                    cdataTextArea.read(new StringReader((String) value), null);
173                } catch (Exception ex) {
174                }
175                return jScrollPaneCDATA;
176            } else if (value instanceof String) {
177                stringRenderer.setText((String) value);
178                return stringRenderer;
179            } else if (value instanceof Boolean) {
180                booleanRenderer.setSelected((Boolean) value);
181                return booleanRenderer;
182            } else if (value instanceof Integer) {
183                integerRenderer.setText(value.toString());
184                return integerRenderer;
185            } else if (value == null) {
186                return null;
187            } else if (value.getClass() == MondrianGuiDef.Join.class) {
188                stringRenderer.setText(generateJoinStr(value));
189
190                stringRenderer.setToolTipText(
191                    workbench.getResourceConverter().getString(
192                        "schemaPropertyCellRenderer.selectJoinObject",
193                        "Select the Join/Table object from Schema tree to "
194                        + "edit."));
195                stringRenderer.setOpaque(true);
196                stringRenderer.setBackground(Color.LIGHT_GRAY);
197                return stringRenderer;
198
199                /* 2: Displaying Join in nested pink boxes
200                SchemaPropertyCellRenderer spcr =
201                    new SchemaPropertyCellRenderer();
202                relationTable.setDefaultRenderer(Object.class, spcr);
203                PropertyTableModel ptm =
204                    new PropertyTableModel(value,SchemaExplorer.DEF_JOIN);
205                relationTable.setModel(ptm);
206                relationTable.getColumnModel().getColumn(0).setMaxWidth(100);
207                relationTable.getColumnModel().getColumn(0).setMinWidth(100);
208                setTableRendererHeight(relationTable, relationRenderer);
209                return relationRenderer;
210                 */
211            } else if (value.getClass()
212                       == MondrianGuiDef.OrdinalExpression.class)
213            {
214                SchemaPropertyCellRenderer spcr =
215                    new SchemaPropertyCellRenderer(workbench);
216                tableRenderer.setDefaultRenderer(Object.class, spcr);
217                PropertyTableModel ptm = new PropertyTableModel(
218                    workbench,
219                    ((MondrianGuiDef.OrdinalExpression) value).expressions[0],
220                    SchemaExplorer.DEF_SQL);
221                tableRenderer.setModel(ptm);
222                tableRenderer.getColumnModel().getColumn(0).setMaxWidth(100);
223                tableRenderer.getColumnModel().getColumn(0).setMinWidth(100);
224                return tableRenderer;
225            } else if (value.getClass()
226                    == MondrianGuiDef.OrdinalExpression.class)
227            {
228                SchemaPropertyCellRenderer spcr =
229                    new SchemaPropertyCellRenderer(workbench);
230                tableRenderer.setDefaultRenderer(Object.class, spcr);
231                PropertyTableModel ptm = new PropertyTableModel(
232                    workbench,
233                    ((MondrianGuiDef.CaptionExpression) value).expressions[0],
234                    SchemaExplorer.DEF_SQL);
235                tableRenderer.setModel(ptm);
236                tableRenderer.getColumnModel().getColumn(0).setMaxWidth(100);
237                tableRenderer.getColumnModel().getColumn(0).setMinWidth(100);
238                return tableRenderer;
239            } else if (value.getClass() == MondrianGuiDef.Formula.class) {
240                SchemaPropertyCellRenderer spcr =
241                    new SchemaPropertyCellRenderer(workbench);
242                tableRenderer.setDefaultRenderer(Object.class, spcr);
243                PropertyTableModel ptm = new PropertyTableModel(
244                    workbench, value, SchemaExplorer.DEF_FORMULA);
245                tableRenderer.setModel(ptm);
246                tableRenderer.getColumnModel().getColumn(0).setMaxWidth(100);
247                tableRenderer.getColumnModel().getColumn(0).setMinWidth(100);
248                return tableRenderer;
249            } else if (value.getClass()
250                       == MondrianGuiDef.CalculatedMemberProperty.class)
251            {
252                SchemaPropertyCellRenderer spcr =
253                    new SchemaPropertyCellRenderer(workbench);
254                tableRenderer.setDefaultRenderer(Object.class, spcr);
255                PropertyTableModel ptm = new PropertyTableModel(
256                    workbench,
257                    value,
258                    SchemaExplorer.DEF_CALCULATED_MEMBER_PROPERTY);
259                tableRenderer.setModel(ptm);
260                tableRenderer.getColumnModel().getColumn(0).setMaxWidth(100);
261                tableRenderer.getColumnModel().getColumn(0).setMinWidth(100);
262                return tableRenderer;
263            } else if (value.getClass() == MondrianGuiDef.Table.class) {
264                SchemaPropertyCellRenderer spcr =
265                    new SchemaPropertyCellRenderer(workbench);
266                tableRenderer.setDefaultRenderer(Object.class, spcr);
267                PropertyTableModel ptm = new PropertyTableModel(
268                    workbench, value, SchemaExplorer.DEF_TABLE);
269                tableRenderer.setModel(ptm);
270                tableRenderer.getColumnModel().getColumn(0).setMaxWidth(100);
271                tableRenderer.getColumnModel().getColumn(0).setMinWidth(100);
272                return tableRenderer;
273            } else if (value.getClass()
274                       == MondrianGuiDef.RelationOrJoin.class)
275            {
276                // REVIEW: Covers View and InlineTable, since Table and Join are
277                // managed above.
278                SchemaPropertyCellRenderer spcr =
279                    new SchemaPropertyCellRenderer(workbench);
280                tableRenderer.setDefaultRenderer(Object.class, spcr);
281                PropertyTableModel ptm = new PropertyTableModel(
282                    workbench, value, SchemaExplorer.DEF_RELATION);
283                tableRenderer.setModel(ptm);
284                return tableRenderer;
285            } else if (value.getClass() == MondrianGuiDef.AggFactCount.class) {
286                SchemaPropertyCellRenderer spcr =
287                    new SchemaPropertyCellRenderer(workbench);
288                tableRenderer.setDefaultRenderer(Object.class, spcr);
289                PropertyTableModel ptm = new PropertyTableModel(
290                    workbench, value, SchemaExplorer.DEF_AGG_FACT_COUNT);
291                tableRenderer.setModel(ptm);
292                tableRenderer.getColumnModel().getColumn(0).setMaxWidth(100);
293                tableRenderer.getColumnModel().getColumn(0).setMinWidth(100);
294                return tableRenderer;
295            } else if (value.getClass() == MondrianGuiDef.Closure.class) {
296                SchemaPropertyCellRenderer spcr =
297                    new SchemaPropertyCellRenderer(workbench);
298                tableRenderer.setDefaultRenderer(Object.class, spcr);
299                PropertyTableModel ptm = new PropertyTableModel(
300                    workbench, value, SchemaExplorer.DEF_CLOSURE);
301                tableRenderer.setModel(ptm);
302                tableRenderer.getColumnModel().getColumn(0).setMaxWidth(100);
303                tableRenderer.getColumnModel().getColumn(0).setMinWidth(100);
304                setTableRendererHeight(tableRenderer, null);
305                return tableRenderer;
306            } else if (value.getClass() == MondrianGuiDef.Property.class) {
307                SchemaPropertyCellRenderer spcr =
308                    new SchemaPropertyCellRenderer(workbench);
309                tableRenderer.setDefaultRenderer(Object.class, spcr);
310                PropertyTableModel ptm = new PropertyTableModel(
311                    workbench, value, SchemaExplorer.DEF_PROPERTY);
312                tableRenderer.setModel(ptm);
313                return tableRenderer;
314            } else {
315                return null;
316            }
317
318        } else {
319            if (value instanceof String) {
320                // Use data from workbenchInfo.properties as tooltip when
321                // available.
322                PropertyTableModel tableModel =
323                    (PropertyTableModel) table.getModel();
324                String className = (tableModel.target.getClass()).getName();
325                int pos = className.lastIndexOf("$");
326                String tooltip = null;
327                if (pos > 0) {
328                    String tipName = (className.substring(pos + 1))
329                                     + ","
330                                     + tableModel.getRowName(row);
331                    tooltip = workbench.getTooltip(tipName);
332                }
333                stringRenderer.setToolTipText(tooltip);
334                stringRenderer.setText((String) value);
335                stringRenderer.setOpaque(true);
336                stringRenderer.setBackground(new java.awt.Color(221, 221, 221));
337                if (isSelected && hasFocus) {
338                    table.editCellAt(row, 1);
339                }
340                return stringRenderer;
341            }
342        }
343        return super.getTableCellRendererComponent(
344            table, value, isSelected, hasFocus, row, column);
345    }
346
347    private String generateJoinStr(Object value) {
348        MondrianGuiDef.Join currentJoin = (MondrianGuiDef.Join) value;
349        String joinStr = "<html>"
350            + generateLeftRightStr(currentJoin.left)
351            + " <b>JOIN</b> "
352            + generateLeftRightStr(currentJoin.right)
353            + "</html>";
354        return joinStr;
355    }
356
357    private String generateLeftRightStr(Object value) {
358        MondrianGuiDef.RelationOrJoin currentObj =
359            (MondrianGuiDef.RelationOrJoin) value;
360        if (currentObj instanceof MondrianGuiDef.Table) {
361            return (((MondrianGuiDef.Table) currentObj).alias == null
362                    || ((MondrianGuiDef.Table) currentObj).alias.equals("")
363                ? ((MondrianGuiDef.Table) currentObj).name
364                : ((MondrianGuiDef.Table) currentObj).alias);
365        }
366        MondrianGuiDef.Join currentJoin = (MondrianGuiDef.Join) currentObj;
367        String joinStr = "("
368            + generateLeftRightStr(currentJoin.left)
369            + " <b>JOIN</b> "
370            + generateLeftRightStr(currentJoin.right)
371            + ")";
372        return joinStr;
373    }
374
375    void setTableRendererHeight(JTable relationTable, JPanel relationRenderer) {
376        int tableH = 0;
377        int tableW = 0;
378        Object value = null;
379        for (int i = 0; i < relationTable.getRowCount(); i++) {
380            TableCellRenderer renderer = relationTable.getCellRenderer(i, 1);
381            Component comp = renderer.getTableCellRendererComponent(
382                relationTable,
383                relationTable.getValueAt(i, 1),
384                false,
385                false,
386                i,
387                1);
388            try {
389                int height = 0;
390                int width = 0;
391                if (comp != null) {
392                    height = comp.getMaximumSize().height;
393                    width = comp.getMaximumSize().width;
394                    relationTable.setRowHeight(i, height);
395                }
396
397                value = relationTable.getValueAt(i, 1);
398                if (value instanceof MondrianGuiDef.RelationOrJoin) {
399                    tableH += comp.getPreferredSize().height;
400                    tableW = Math.max(
401                        tableW, comp.getPreferredSize().width + stringRenderer
402                            .getMaximumSize().width);
403                } else if (value == null) {
404                    tableH += stringRenderer.getMaximumSize().height;
405                    tableW = Math.max(
406                        tableW, stringRenderer.getMaximumSize().width * 2);
407                } else {
408                    tableH += height;
409                    tableW = Math.max(tableW, width * 2);
410                }
411            } catch (Exception ea) {
412            }
413        }
414        // table height  changes
415        relationTable.setPreferredSize(
416            new Dimension(
417                tableW, tableH));
418        // scrollpane adjusts to new table height, it also changes scrollpanes'
419        // preferred size values
420        relationTable.setPreferredScrollableViewportSize(
421            relationTable.getPreferredSize());
422        if (relationRenderer != null) {
423            relationRenderer.setPreferredSize(
424                jScrollPaneT.getPreferredSize());
425            relationRenderer.setMaximumSize(
426                jScrollPaneT.getPreferredSize());
427        }
428    }
429}
430
431// End SchemaPropertyCellRenderer.java