1 /*
2  * This file is part of the LibreOffice project.
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * This file incorporates work covered by the following license notice:
9  *
10  *   Licensed to the Apache Software Foundation (ASF) under one or more
11  *   contributor license agreements. See the NOTICE file distributed
12  *   with this work for additional information regarding copyright
13  *   ownership. The ASF licenses this file to you under the Apache
14  *   License, Version 2.0 (the "License"); you may not use this file
15  *   except in compliance with the License. You may obtain a copy of
16  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
17  */
18 package com.sun.star.wizards.ui;
19 
20 import javax.swing.ListModel;
21 import com.sun.star.awt.ActionEvent;
22 import com.sun.star.awt.Size;
23 import com.sun.star.awt.XActionListener;
24 import com.sun.star.awt.XButton;
25 import com.sun.star.awt.XControl;
26 import com.sun.star.awt.XControlModel;
27 import com.sun.star.awt.XFixedText;
28 import com.sun.star.awt.XItemEventBroadcaster;
29 import com.sun.star.awt.XItemListener;
30 import com.sun.star.awt.XWindow;
31 import com.sun.star.lang.EventObject;
32 import com.sun.star.uno.UnoRuntime;
33 import com.sun.star.wizards.common.HelpIds;
34 import com.sun.star.wizards.common.Helper;
35 import com.sun.star.wizards.common.IRenderer;
36 import com.sun.star.wizards.common.PropertyNames;
37 import com.sun.star.wizards.common.PropertySetHelper;
38 import com.sun.star.wizards.ui.event.XActionListenerAdapter;
39 
40 public class ButtonList implements XItemEventBroadcaster, XActionListener
41 {
42 
43     private XFixedText lblImageText;
44     private XButton btnBack;
45     private XButton btnNext;
46     private XFixedText lblCounter;
47     private XControl m_aButtons[];
48     private boolean benabled = true;
49     private UnoDialog2 oUnoDialog;
50     private Size gap = new Size(4, 4);
51     private int cols = 4;
52     private int rows = 3;
53     private Size m_aButtonSize = new Size(20, 20);
54     private Size pos;
55     private boolean showButtons = true;
56     private Short step;
57     private static final boolean refreshOverNull = true;
58     private static final int imageTextLines = 1;
59     private boolean rowSelect = false;
60     public int tabIndex;
61     private String m_aControlName = "il";
62     private int m_nCurrentSelection = -1;
63     private int pageStart = 0;
64     public int helpURL = 0;
65     private IRenderer renderer;
66     private ListModel listModel;
67     private IRenderer counterRenderer = new SimpleCounterRenderer();
68     private static final int LINE_HEIGHT = 8;
69 
setName(String _sName)70     public void setName(String _sName)
71     {
72         m_aControlName = _sName;
73     }
74 
75     /** Setter for property m_aButtonSize.
76      * @param imageSize  New value of property m_aButtonSize.
77      */
setButtonSize(Size imageSize)78     public void setButtonSize(Size imageSize)
79     {
80         this.m_aButtonSize = imageSize;
81     }
82 
disposing(EventObject arg0)83     public void disposing(EventObject arg0)
84     {
85     }
86 
create(UnoDialog2 dialog)87     public void create(UnoDialog2 dialog)
88     {
89         oUnoDialog = dialog;
90 
91         int imageTextHeight = imageTextLines * LINE_HEIGHT;
92 
93         int nXPos = pos.Width + 1;
94         int nYPos = pos.Height + (m_aButtonSize.Height + gap.Height) * rows + gap.Height;
95         int nWidth = cols * (m_aButtonSize.Width + gap.Width) + gap.Width - 2;
96 
97         lblImageText = dialog.insertLabel(m_aControlName + "_imageText",
98                 new String[]
99                 {
100                     PropertyNames.PROPERTY_HEIGHT,
101                     PropertyNames.PROPERTY_HELPURL,
102                     PropertyNames.PROPERTY_LABEL,
103                     PropertyNames.PROPERTY_POSITION_X,
104                     PropertyNames.PROPERTY_POSITION_Y,
105                     PropertyNames.PROPERTY_STEP,
106                     PropertyNames.PROPERTY_TABINDEX,
107                     "Tabstop",
108                     PropertyNames.PROPERTY_WIDTH
109                 },
110                 new Object[]
111                 {
112                     Integer.valueOf(imageTextHeight),
113                     PropertyNames.EMPTY_STRING,
114                     "(1)",
115                     Integer.valueOf(nXPos),
116                     Integer.valueOf(nYPos),
117                     step,
118                     Short.valueOf((short) 0),
119                     Boolean.FALSE,
120                     Integer.valueOf(nWidth)
121                 });
122 
123 
124         if (showButtons)
125         {
126             final String[] pNames1 = new String[]
127             {
128                 PropertyNames.PROPERTY_HEIGHT,
129                 PropertyNames.PROPERTY_HELPURL,
130                 PropertyNames.PROPERTY_POSITION_X,
131                 PropertyNames.PROPERTY_POSITION_Y,
132                 PropertyNames.PROPERTY_STEP,
133                 PropertyNames.PROPERTY_TABINDEX,
134                 "Tabstop",
135                 PropertyNames.PROPERTY_WIDTH
136             };
137 
138             final Integer btnSize = Integer.valueOf(14);
139 
140 // TODO: if list of strings not the same length of list object, office will die.
141             btnBack = dialog.insertButton(m_aControlName + "_btnBack", new XActionListenerAdapter() {
142                         @Override
143                         public void actionPerformed(ActionEvent event) {
144                             prevPage();
145                         }
146                     }, pNames1, new Object[]
147                     {
148                         btnSize,
149                         HelpIds.getHelpIdString(helpURL++),
150                         Integer.valueOf(pos.Width),
151                         Integer.valueOf(pos.Height + (m_aButtonSize.Height + gap.Height) * rows + gap.Height + imageTextHeight + 1),
152                         step,
153                         Short.valueOf((short) (tabIndex + 1)),
154                         Boolean.TRUE,
155                         btnSize
156                     });
157 
158             btnNext = dialog.insertButton(m_aControlName + "_btnNext", new XActionListenerAdapter() {
159                         @Override
160                         public void actionPerformed(ActionEvent event) {
161                             nextPage();
162                         }
163                     }, pNames1, new Object[]
164                     {
165                         btnSize,
166                         HelpIds.getHelpIdString(helpURL++),
167                         Integer.valueOf(pos.Width + (m_aButtonSize.Width + gap.Width) * cols + gap.Width - btnSize.intValue() + 1),
168                         Integer.valueOf(pos.Height + (m_aButtonSize.Height + gap.Height) * rows + gap.Height + imageTextHeight + 1),
169                         step,
170                         Short.valueOf((short) (tabIndex + 2)),
171                         Boolean.TRUE,
172                         btnSize
173                     });
174 
175             lblCounter = dialog.insertLabel(m_aControlName + "_lblCounter", pNames1, new Object[]
176                     {
177                         Integer.valueOf(LINE_HEIGHT),
178                         PropertyNames.EMPTY_STRING,
179                         Integer.valueOf(pos.Width + btnSize.intValue() + 1),
180                         Integer.valueOf(pos.Height + (m_aButtonSize.Height + gap.Height) * rows + gap.Height + imageTextHeight + ((btnSize.intValue() - LINE_HEIGHT) / 2)),
181                         step,
182                         Short.valueOf((short) 0),
183                         Boolean.FALSE,
184                         Integer.valueOf(cols * (m_aButtonSize.Width + gap.Width) + gap.Width - 2 * btnSize.intValue() - 1)
185                     });
186 
187             Helper.setUnoPropertyValue(getModel(lblCounter), PropertyNames.PROPERTY_ALIGN, Short.valueOf((short) 1));
188             Helper.setUnoPropertyValue(getModel(btnBack), PropertyNames.PROPERTY_LABEL, "<");
189             Helper.setUnoPropertyValue(getModel(btnNext), PropertyNames.PROPERTY_LABEL, ">");
190 
191 
192         }
193 
194         m_tabIndex = Short.valueOf((short) tabIndex);
195 
196         m_aButtons = new XControl[rows * cols];
197 
198         m_aButtonHeight = Integer.valueOf(m_aButtonSize.Height);
199         m_aButtonWidth = Integer.valueOf(m_aButtonSize.Width);
200 
201         for (int r = 0; r < rows; r++)
202         {
203             for (int c = 0; c < cols; c++)
204             {
205                 XButton aButton = createButton(dialog, r, c);
206                 XControl aControl = UnoRuntime.queryInterface(XControl.class, aButton);
207                 m_aButtons[r * cols + c] = aControl;
208             }
209         }
210         refreshImages();
211     }
212 
213     private Integer m_aButtonHeight;
214     private Integer m_aButtonWidth;
215     private Short m_tabIndex;
216 
createButton(UnoDialog2 dialog, int _row, int _col)217     private XButton createButton(UnoDialog2 dialog, int _row, int _col)
218     {
219         String sButtonName = m_aControlName + "_button" + (_row * cols + _col);
220         int nButtonX = getButtonPosX(_col);
221         int nButtonY = getButtonPosY(_row);
222         XButton aButton = dialog.insertImageButton(sButtonName, this,
223                 new String[]
224                 {
225                     /* PropertyNames.PROPERTY_BORDER, */
226                     /* "BackgroundColor", */
227                     PropertyNames.PROPERTY_HEIGHT,
228                     PropertyNames.PROPERTY_HELPURL,
229                     /* PropertyNames.PROPERTY_LABEL, */
230                     PropertyNames.PROPERTY_POSITION_X,
231                     PropertyNames.PROPERTY_POSITION_Y,
232                     /* "ScaleImage", */
233                     PropertyNames.PROPERTY_STEP,
234                     PropertyNames.PROPERTY_TABINDEX,
235                     "Tabstop",
236                     "Toggle",
237                     PropertyNames.PROPERTY_WIDTH
238                 },
239                 new Object[]
240                 {
241                     /* Short.valueOf((short) 1), */ /* NO_BORDER, */
242                     /* BACKGROUND_COLOR, */
243                     m_aButtonHeight,
244                     HelpIds.getHelpIdString(helpURL++),
245                     /* "Test", */
246                     Integer.valueOf(nButtonX),
247                     Integer.valueOf(nButtonY),
248                     /* scaleImages, */
249                     step,
250                     m_tabIndex,
251                     Boolean.TRUE,
252                     Boolean.TRUE, /* Toggle */
253                     m_aButtonWidth
254                 });
255 
256         XWindow win = UnoRuntime.queryInterface(XWindow.class, aButton);
257         win.setEnable(true);
258         win.setVisible(true);
259         return aButton;
260     }
261 
getButtonPosX(int _col)262     private int getButtonPosX(int _col)
263     {
264         return pos.Width + _col * (m_aButtonSize.Width + gap.Width) + gap.Width;
265     }
266 
getButtonPosY(int _row)267     private int getButtonPosY(int _row)
268     {
269         return pos.Height + _row * (m_aButtonSize.Height + gap.Height) + gap.Height;
270     }
271 
refreshImages()272     private void refreshImages()
273     {
274         if (showButtons)
275         {
276             refreshCounterText();
277         }
278         if (refreshOverNull)
279         {
280             for (int i = 0; i < m_aButtons.length; i++)
281             {
282                 setVisible(m_aButtons[i], false);
283             }
284         }
285         for (int i = 0; i < m_aButtons.length; i++)
286         {
287             String oResource = getObjectFor(i);
288             if (oResource == null)
289                 continue;
290             oUnoDialog.getPeerConfiguration().setImageUrl(m_aButtons[i].getModel(), oResource);
291             boolean bTabStop = Boolean.TRUE; // focusable ? Boolean.TRUE : Boolean.FALSE;
292             Helper.setUnoPropertyValue(m_aButtons[i].getModel(), "Tabstop", bTabStop);
293             if (refreshOverNull)
294             {
295                 setVisible(m_aButtons[i], true);
296             }
297         }
298     }
299 
refreshCounterText()300     private void refreshCounterText()
301     {
302         Helper.setUnoPropertyValue(getModel(lblCounter), PropertyNames.PROPERTY_LABEL, counterRenderer.render(new Counter(pageStart + 1, pageEnd(), listModel.getSize())));
303     }
304 
pageEnd()305     private int pageEnd()
306     {
307         int i = pageStart + cols * rows;
308         if (i > listModel.getSize() - 1)
309         {
310             return listModel.getSize();
311         }
312         else
313         {
314             return i;
315         }
316     }
317 
318     /** Utility field holding list of ItemListeners. */
319     private transient java.util.ArrayList<XItemListener> m_aItemListenerList;
setVisible(Object control, boolean visible)320     private void setVisible(Object control, boolean visible)
321     {
322         final XWindow xWindow = UnoRuntime.queryInterface(XWindow.class, control);
323         xWindow.setVisible(visible);
324     }
325 
326     /**
327      * @param i
328      * @return the String in the list model corresponding to the given image url
329      */
getObjectFor(int i)330     private String getObjectFor(int i)
331     {
332         int ii = getIndexFor(i);
333         if (listModel.getSize() <= ii)
334         {
335             return null;
336         }
337         else
338         {
339             return (String)listModel.getElementAt(ii);
340         }
341     }
342 
343     /**
344      * @param i
345      * @return the index in the listModel for the given image index.
346      */
getIndexFor(int i)347     private int getIndexFor(int i)
348     {
349         return pageStart + i;
350     }
351 
352     /** Registers ItemListener to receive events.
353      * @param listener The listener to register.
354      */
addItemListener(XItemListener listener)355     public synchronized void addItemListener(XItemListener listener)
356     {
357         if (m_aItemListenerList == null)
358         {
359             m_aItemListenerList = new java.util.ArrayList<XItemListener>();
360         }
361         m_aItemListenerList.add(listener);
362     }
363 
364     /** Removes ItemListener from the list of listeners.
365      * @param listener The listener to remove.
366      */
removeItemListener(XItemListener listener)367     public synchronized void removeItemListener(XItemListener listener)
368     {
369         if (m_aItemListenerList != null)
370         {
371             m_aItemListenerList.remove(listener);
372         }
373     }
374 
375     /** Notifies all registered listeners about the event.
376      *
377      */
fireItemSelected()378     private void fireItemSelected()
379     {
380         java.util.ArrayList<XItemListener> list;
381         synchronized(this)
382         {
383             if (m_aItemListenerList == null)
384             {
385                 return;
386             }
387             list = (java.util.ArrayList<XItemListener>) m_aItemListenerList.clone();
388         }
389         for (int i = 0; i < list.size(); i++)
390         {
391             list.get(i).itemStateChanged(null);
392         }
393     }
394 
getListModel()395     private ListModel getListModel()
396     {
397         return listModel;
398     }
399 
getSelected()400     public int getSelected()
401     {
402         return m_nCurrentSelection;
403     }
404 
setCols(int i)405     public void setCols(int i)
406     {
407         cols = i;
408     }
409 
setGap(Size size)410     public void setGap(Size size)
411     {
412         gap = size;
413     }
414 
setListModel(ListModel model)415     public void setListModel(ListModel model)
416     {
417         listModel = model;
418     }
419 
setStep(Short short1)420     public void setStep(Short short1)
421     {
422         step = short1;
423     }
424 
setPageStart(int i)425     private void setPageStart(int i)
426     {
427         if (i == pageStart)
428         {
429             return;
430         }
431         pageStart = i;
432         enableButtons();
433         refreshImages();
434     }
435 
setPos(Size _size)436     public void setPos(Size _size)
437     {
438         pos = _size;
439     }
440 
setRenderer(IRenderer _renderer)441     public void setRenderer(IRenderer _renderer)
442     {
443         this.renderer = _renderer;
444     }
445 
setRows(int i)446     public void setRows(int i)
447     {
448         rows = i;
449     }
450 
setSelected(int i)451     public void setSelected(int i)
452     {
453         if (rowSelect && (i >= 0))
454         {
455             i = (i / cols) * cols;
456         }
457         if (m_nCurrentSelection == i)
458         {
459             return;
460         }
461         m_nCurrentSelection = i;
462         refreshImageText();
463         refreshSelection();
464         fireItemSelected();
465     }
466 
467     /**
468      * set the text under the button list
469      */
refreshImageText()470     private void refreshImageText()
471     {
472         String sText;
473         Object item = m_nCurrentSelection >= 0 ? getListModel().getElementAt(m_nCurrentSelection) : null;
474         if (item != null) {
475             sText = PropertyNames.SPACE + renderer.render(item);
476         }
477         else {
478             sText = "";
479         }
480         Helper.setUnoPropertyValue(getModel(lblImageText), PropertyNames.PROPERTY_LABEL, sText);
481     }
482 
setShowButtons(boolean b)483     public void setShowButtons(boolean b)
484     {
485         showButtons = b;
486     }
487 
nextPage()488     private void nextPage()
489     {
490         if (pageStart < getListModel().getSize() - rows * cols)
491         {
492             setPageStart(pageStart + rows * cols);
493         }
494     }
495 
prevPage()496     private void prevPage()
497     {
498         if (pageStart == 0)
499         {
500             return;
501         }
502         int i = pageStart - rows * cols;
503         if (i < 0)
504         {
505             i = 0;
506         }
507         setPageStart(i);
508     }
509 
enableButtons()510     private void enableButtons()
511     {
512         enable(btnNext, Boolean.valueOf(pageStart + rows * cols < listModel.getSize()));
513         enable(btnBack, Boolean.valueOf(pageStart > 0));
514     }
515 
enable(Object control, Boolean enable)516     private void enable(Object control, Boolean enable)
517     {
518         Helper.setUnoPropertyValue(getModel(control), PropertyNames.PROPERTY_ENABLED, enable);
519     }
520 
getModel(Object control)521     private Object getModel(Object control)
522     {
523         return UnoRuntime.queryInterface(XControl.class, control).getModel();
524     }
525 
526     private static class SimpleCounterRenderer implements IRenderer
527     {
528 
render(Object counter)529         public String render(Object counter)
530         {
531             return PropertyNames.EMPTY_STRING + ((Counter) counter).start + ".." + ((Counter) counter).end + "/" + ((Counter) counter).max;
532         }
533     }
534 
535     private static class Counter
536     {
537 
538         private int start,  end,  max;
539 
Counter(int start_, int end_, int max_)540         private Counter(int start_, int end_, int max_)
541         {
542             start = start_;
543             end = end_;
544             max = max_;
545         }
546     }
547 
isenabled()548     public boolean isenabled()
549     {
550         return benabled;
551     }
552 
setenabled(boolean b)553     public void setenabled(boolean b)
554     {
555 
556         for (int i = 0; i < m_aButtons.length; i++)
557         {
558             UnoDialog2.setEnabled(m_aButtons[i], b);
559         }
560         UnoDialog2.setEnabled(lblImageText, b);
561         if (showButtons)
562         {
563             UnoDialog2.setEnabled(btnBack, b);
564             UnoDialog2.setEnabled(btnNext, b);
565             UnoDialog2.setEnabled(lblCounter, b);
566         }
567         benabled = b;
568     }
569 
570     /**
571      * refresh on all buttons, the selected button will get state pressed
572      */
refreshSelection()573     private void refreshSelection()
574     {
575         // reset all buttons to not set
576         for (int i = 0; i < m_aButtons.length; i++)
577         {
578             if (m_aButtons[i] != null)
579             {
580                 XControlModel xModel = (XControlModel)UnoDialog2.getModel(m_aButtons[i]);
581                 PropertySetHelper aHelper = new PropertySetHelper(xModel);
582                 if (i == m_nCurrentSelection)
583                 {
584                     final short one = 1;
585                     aHelper.setPropertyValueDontThrow(PropertyNames.PROPERTY_STATE, Short.valueOf(one));
586                 }
587                 else
588                 {
589                     final short zero = 0;
590                     aHelper.setPropertyValueDontThrow(PropertyNames.PROPERTY_STATE, Short.valueOf(zero));
591                 }
592             }
593         }
594     }
595 
596     /**
597      * implementation of XActionListener
598      * will call if a button from the m_aButtonList is pressed.
599      */
actionPerformed(com.sun.star.awt.ActionEvent actionEvent)600     public void actionPerformed(com.sun.star.awt.ActionEvent actionEvent)
601     {
602         XControlModel xModel = (XControlModel)UnoDialog2.getModel(actionEvent.Source);
603         PropertySetHelper aHelper = new PropertySetHelper(xModel);
604 
605         int nState = aHelper.getPropertyValueAsInteger(PropertyNames.PROPERTY_STATE, -1);
606         if (nState == 0)
607         {
608             // this will avoid a wrong state, if already pressed.
609             aHelper.setPropertyValueDontThrow(PropertyNames.PROPERTY_STATE, Short.valueOf((short)1));
610         }
611 
612         // check which Button is pressed.
613         String sControlName = aHelper.getPropertyValueAsString(PropertyNames.PROPERTY_NAME, PropertyNames.EMPTY_STRING);
614         final String sButton = sControlName.substring(7 + m_aControlName.length());
615         int nButton = Integer.parseInt(sButton);
616 
617         int index = getIndexFor(nButton);
618         if (index < listModel.getSize())
619         {
620             setSelected(index);
621         }
622 
623     }
624 
625 
626 }
627