Skip to content

Commit 0755c7c

Browse files
cmaglieFederico Fissore
authored and
Federico Fissore
committed
Library installer UI
1 parent 0b9223c commit 0755c7c

File tree

15 files changed

+1312
-164
lines changed

15 files changed

+1312
-164
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
/*
2+
* This file is part of Arduino.
3+
*
4+
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
5+
*
6+
* Arduino is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, write to the Free Software
18+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19+
*
20+
* As a special exception, you may use this file as part of a free software
21+
* library without restriction. Specifically, if other files instantiate
22+
* templates or use macros or inline functions from this file, or you compile
23+
* this file and link it with other files to produce an executable, this
24+
* file does not by itself cause the resulting executable to be covered by
25+
* the GNU General Public License. This exception does not however
26+
* invalidate any other reasons why the executable file might be covered by
27+
* the GNU General Public License.
28+
*/
29+
package cc.arduino.libraries.contributions.ui;
30+
31+
import static processing.app.I18n._;
32+
import static processing.app.I18n.format;
33+
34+
import java.awt.Color;
35+
import java.awt.Component;
36+
import java.awt.Dimension;
37+
import java.awt.Insets;
38+
import java.awt.Rectangle;
39+
import java.awt.event.ActionEvent;
40+
import java.awt.event.ActionListener;
41+
42+
import javax.swing.AbstractCellEditor;
43+
import javax.swing.Box;
44+
import javax.swing.BoxLayout;
45+
import javax.swing.JButton;
46+
import javax.swing.JPanel;
47+
import javax.swing.JTable;
48+
import javax.swing.JTextPane;
49+
import javax.swing.border.EmptyBorder;
50+
import javax.swing.event.HyperlinkEvent;
51+
import javax.swing.event.HyperlinkListener;
52+
import javax.swing.table.TableCellEditor;
53+
import javax.swing.table.TableCellRenderer;
54+
import javax.swing.text.BadLocationException;
55+
import javax.swing.text.Document;
56+
import javax.swing.text.html.HTMLDocument;
57+
import javax.swing.text.html.StyleSheet;
58+
59+
import processing.app.Base;
60+
import cc.arduino.libraries.contributions.ContributedLibrary;
61+
import cc.arduino.libraries.contributions.ui.LibrariesIndexTableModel.ContributedLibraryReleases;
62+
63+
@SuppressWarnings("serial")
64+
public class ContributedLibraryTableCell extends AbstractCellEditor implements
65+
TableCellEditor, TableCellRenderer {
66+
67+
private JPanel panel;
68+
private JTextPane description;
69+
private JButton installButton;
70+
private JButton removeButton;
71+
private Component removeButtonPlaceholder;
72+
private Component installButtonPlaceholder;
73+
74+
public ContributedLibraryTableCell() {
75+
description = new JTextPane();
76+
description.setInheritsPopupMenu(true);
77+
Insets margin = description.getMargin();
78+
margin.bottom = 0;
79+
description.setMargin(margin);
80+
description.setContentType("text/html");
81+
Document doc = description.getDocument();
82+
if (doc instanceof HTMLDocument) {
83+
HTMLDocument html = (HTMLDocument) doc;
84+
StyleSheet stylesheet = html.getStyleSheet();
85+
stylesheet.addRule("body { margin: 0; padding: 0;"
86+
+ "font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"
87+
+ "font-size: 100%;" + "font-size: 0.95em; }");
88+
}
89+
description.setOpaque(false);
90+
description.setBorder(new EmptyBorder(4, 7, 7, 7));
91+
description.setHighlighter(null);
92+
description.setEditable(false);
93+
description.addHyperlinkListener(new HyperlinkListener() {
94+
@Override
95+
public void hyperlinkUpdate(HyperlinkEvent e) {
96+
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
97+
Base.openURL(e.getDescription());
98+
}
99+
}
100+
});
101+
102+
{
103+
installButton = new JButton(_("Install"));
104+
installButton.addActionListener(new ActionListener() {
105+
@Override
106+
public void actionPerformed(ActionEvent e) {
107+
onInstall(editorValue.getSelected());
108+
}
109+
});
110+
int width = installButton.getPreferredSize().width;
111+
installButtonPlaceholder = Box.createRigidArea(new Dimension(width, 1));
112+
}
113+
114+
{
115+
removeButton = new JButton(_("Remove"));
116+
removeButton.addActionListener(new ActionListener() {
117+
@Override
118+
public void actionPerformed(ActionEvent e) {
119+
onRemove(editorValue.getInstalled());
120+
}
121+
});
122+
int width = removeButton.getPreferredSize().width;
123+
removeButtonPlaceholder = Box.createRigidArea(new Dimension(width, 1));
124+
}
125+
126+
panel = new JPanel();
127+
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
128+
129+
panel.add(description);
130+
panel.add(Box.createHorizontalStrut(5));
131+
panel.add(installButton);
132+
panel.add(installButtonPlaceholder);
133+
panel.add(Box.createHorizontalStrut(5));
134+
panel.add(removeButton);
135+
panel.add(removeButtonPlaceholder);
136+
panel.add(Box.createHorizontalStrut(5));
137+
}
138+
139+
protected void onRemove(ContributedLibrary contributedPlatform) {
140+
// Empty
141+
}
142+
143+
protected void onInstall(ContributedLibrary contributedPlatform) {
144+
// Empty
145+
}
146+
147+
public Component getTableCellRendererComponent(JTable table, Object value,
148+
boolean isSelected,
149+
boolean hasFocus, int row,
150+
int column) {
151+
parentTable = table;
152+
return getUpdatedCellComponent(value, isSelected, row);
153+
}
154+
155+
private ContributedLibraryReleases editorValue;
156+
private JTable parentTable;
157+
158+
@Override
159+
public Object getCellEditorValue() {
160+
return editorValue;
161+
}
162+
163+
@Override
164+
public Component getTableCellEditorComponent(JTable table, Object value,
165+
boolean isSelected, int row,
166+
int column) {
167+
parentTable = table;
168+
editorValue = (ContributedLibraryReleases) value;
169+
return getUpdatedCellComponent(value, true, row);
170+
}
171+
172+
private Component getUpdatedCellComponent(Object value, boolean isSelected,
173+
int row) {
174+
ContributedLibraryReleases releases = (ContributedLibraryReleases) value;
175+
ContributedLibrary selectedLib = releases.getSelected();
176+
ContributedLibrary installedLib = releases.getInstalled();
177+
178+
boolean removable, installable, upgradable;
179+
if (installedLib == null) {
180+
installable = true;
181+
removable = false;
182+
upgradable = false;
183+
} else {
184+
installable = false;
185+
removable = !installedLib.isReadOnly();
186+
upgradable = (selectedLib != installedLib);
187+
}
188+
if (installable)
189+
installButton.setText(_("Install"));
190+
if (upgradable)
191+
installButton.setText(_("Upgrade"));
192+
installButton.setVisible(installable || upgradable);
193+
installButtonPlaceholder.setVisible(!(installable || upgradable));
194+
removeButton.setVisible(removable);
195+
removeButtonPlaceholder.setVisible(!removable);
196+
197+
String name = selectedLib.getName();
198+
String author = selectedLib.getAuthor();
199+
// String maintainer = selectedLib.getMaintainer();
200+
String website = selectedLib.getWebsite();
201+
String sentence = selectedLib.getSentence();
202+
String paragraph = selectedLib.getParagraph();
203+
String availableVer = selectedLib.getVersion();
204+
String url = selectedLib.getUrl();
205+
206+
String midcolor = isSelected ? "#000000" : "#888888";
207+
208+
String desc = "<html><body>";
209+
// Library name
210+
desc += format("<b><font size=\"+1\">{0}</font></b>", name);
211+
212+
desc += format("<font color=\"{0}\">", midcolor);
213+
214+
if (author != null && !author.isEmpty()) {
215+
desc += format(" by <a href=\"{0}\">{1}</a>", website, author);
216+
}
217+
desc += "<br />";
218+
219+
if (sentence != null) {
220+
desc += format("<b>{0}</b><br />", sentence);
221+
if (paragraph != null && !paragraph.isEmpty())
222+
desc += format("{0}<br />", paragraph);
223+
desc += "<br />";
224+
}
225+
226+
desc += "</font>"; // close midcolor
227+
228+
// If the selected lib is available from repository...
229+
if (url != null) {
230+
desc += format(_("Available version: <b>{0}</b>"), availableVer);
231+
removeButton.setText(_("Remove"));
232+
} else {
233+
removeButton.setText(_("Delete"));
234+
}
235+
desc += "<br />";
236+
237+
if (installedLib != null) {
238+
String installedVer = installedLib.getVersion();
239+
if (installedVer == null)
240+
installedVer = "Legacy";
241+
desc += format(_("Installed version: <b>{0}</b>"), installedVer);
242+
if (installedLib.isReadOnly())
243+
desc += " " + _("(Bundled)");
244+
}
245+
desc += "<br />";
246+
247+
desc += "</body></html>";
248+
description.setText(desc);
249+
description.setBackground(Color.WHITE);
250+
251+
try {
252+
// for modelToView to work, the text area has to be sized. It doesn't
253+
// matter if it's visible or not.
254+
255+
// See:
256+
// http://stackoverflow.com/questions/3081210/how-to-set-jtextarea-to-have-height-that-matches-the-size-of-a-text-it-contains
257+
int width = parentTable.getBounds().width;
258+
width -= installButtonPlaceholder.getPreferredSize().width;
259+
width -= removeButtonPlaceholder.getPreferredSize().width;
260+
Dimension minimalSize = new Dimension(width, 10);
261+
description.setPreferredSize(minimalSize);
262+
description.setSize(minimalSize);
263+
264+
Rectangle r = description.modelToView(description.getDocument()
265+
.getLength());
266+
r.height += description.modelToView(0).y; // add margins
267+
Dimension d = new Dimension(minimalSize.width, r.y + r.height);
268+
description.setPreferredSize(d);
269+
} catch (BadLocationException e) {
270+
e.printStackTrace();
271+
}
272+
273+
if (isSelected) {
274+
panel.setBackground(parentTable.getSelectionBackground());
275+
panel.setForeground(parentTable.getSelectionForeground());
276+
} else {
277+
panel.setBackground(parentTable.getBackground());
278+
panel.setForeground(parentTable.getForeground());
279+
}
280+
281+
return panel;
282+
}
283+
284+
void setEnabled(boolean enabled) {
285+
installButton.setEnabled(enabled);
286+
removeButton.setEnabled(enabled);
287+
}
288+
289+
public void invalidate() {
290+
panel.invalidate();
291+
}
292+
293+
}

0 commit comments

Comments
 (0)