1 package jp.sourceforge.stigmata.ui.swing.mds;
7 import java.awt.BorderLayout;
8 import java.awt.Dimension;
9 import java.awt.FlowLayout;
10 import java.awt.GridLayout;
11 import java.awt.event.ActionEvent;
12 import java.awt.event.ActionListener;
13 import java.awt.event.ComponentAdapter;
14 import java.awt.event.ComponentEvent;
16 import java.util.HashMap;
19 import javax.swing.Action;
20 import javax.swing.Box;
21 import javax.swing.JButton;
22 import javax.swing.JCheckBox;
23 import javax.swing.JComboBox;
24 import javax.swing.JLabel;
25 import javax.swing.JPanel;
26 import javax.swing.JScrollPane;
27 import javax.swing.JTextField;
28 import javax.swing.JToolBar;
30 import jp.sourceforge.stigmata.BirthmarkContext;
31 import jp.sourceforge.stigmata.BirthmarkEnvironment;
32 import jp.sourceforge.stigmata.BirthmarkSet;
33 import jp.sourceforge.stigmata.ComparisonPair;
34 import jp.sourceforge.stigmata.ui.swing.ClippedLRListCellRenderer;
35 import jp.sourceforge.stigmata.ui.swing.GUIUtility;
36 import jp.sourceforge.stigmata.ui.swing.PopupButton;
37 import jp.sourceforge.stigmata.ui.swing.StigmataFrame;
38 import jp.sourceforge.stigmata.ui.swing.actions.SaveAction;
39 import jp.sourceforge.talisman.i18n.MessageManager;
40 import jp.sourceforge.talisman.i18n.Messages;
41 import jp.sourceforge.talisman.i18n.ResourceNotFoundException;
42 import jp.sourceforge.talisman.mds.Item;
43 import jp.sourceforge.talisman.mds.MdsMethod;
44 import jp.sourceforge.talisman.mds.Table;
45 import jp.sourceforge.talisman.mds.ui.MdsGraphSetting;
46 import jp.sourceforge.talisman.mds.ui.mark.DrawerFactory;
47 import jp.sourceforge.talisman.mds.ui.swing.MdsPane;
48 import jp.sourceforge.talisman.mds.ui.swing.actions.AntiClockwiseRotateAction;
49 import jp.sourceforge.talisman.mds.ui.swing.actions.ClearAction;
50 import jp.sourceforge.talisman.mds.ui.swing.actions.ClockwiseRotateAction;
51 import jp.sourceforge.talisman.mds.ui.swing.actions.ClusteringAction;
52 import jp.sourceforge.talisman.mds.ui.swing.actions.HorizontalFlipAction;
53 import jp.sourceforge.talisman.mds.ui.swing.actions.VerticalFlipAction;
54 import jp.sourceforge.talisman.mds.ui.swing.actions.ZoomEnabler;
55 import jp.sourceforge.talisman.mds.ui.swing.actions.ZoomInAction;
56 import jp.sourceforge.talisman.mds.ui.swing.actions.ZoomOutAction;
60 * @author Haruaki TAMADA
63 public class MdsViewerPane extends JPanel implements ZoomEnabler, MessageManager{
64 private static final long serialVersionUID = -7256554014379112897L;
65 private static final int[] ZOOM_PATTERN = { 30, 40, 50, 75, 100, 125, 150,
68 private StigmataFrame stigmata;
69 private BirthmarkSet[] set;
70 private BirthmarkContext context;
71 private MdsPane mdspane;
72 private MdsGraphSetting setting;
73 private LabelMap labels;
75 private int currentZoomPattern = 4;
76 private boolean userInputtedValue = false;
77 private JTextField zoomRatio;
78 private ZoomInAction zoomin;
79 private ZoomOutAction zoomout;
81 public MdsViewerPane(StigmataFrame stigmata, BirthmarkSet[] set, BirthmarkContext context){
82 this.stigmata = stigmata;
83 this.context = context;
88 } catch(ResourceNotFoundException e){
90 throw new InternalError(e.getMessage());
97 userInputtedValue = false;
98 zoom(ZOOM_PATTERN[currentZoomPattern]);
102 public void zoomOut(){
103 if(!userInputtedValue){
104 currentZoomPattern--;
106 userInputtedValue = false;
107 zoom(ZOOM_PATTERN[currentZoomPattern]);
111 public void zoom(int ratio){
112 for(int i = 0; i < ZOOM_PATTERN.length; i++){
113 if(ratio <= ZOOM_PATTERN[i]){
114 currentZoomPattern = i;
118 if(userInputtedValue && ratio < ZOOM_PATTERN[0]){
119 currentZoomPattern = -1;
121 if(userInputtedValue && ratio > ZOOM_PATTERN[ZOOM_PATTERN.length - 1]){
122 currentZoomPattern = ZOOM_PATTERN.length - 1;
124 zoomin.setEnabled(currentZoomPattern < (ZOOM_PATTERN.length - 1));
125 zoomout.setEnabled(currentZoomPattern != 0);
127 zoomRatio.setText(ratio + " %");
128 mdspane.setZoomRatio(ratio);
132 public Messages getMessages(){
133 return stigmata.getMessages();
136 private Table<String> initData(BirthmarkSet[] set, BirthmarkContext context){
137 Table<String> table = new Table<String>();
139 for(int i = 0; i < set.length; i++){
140 for(int j = 0; j <= i; j++){
141 ComparisonPair pair = new ComparisonPair(set[i], set[j], context);
142 table.addValue(set[i].getName(), set[j].getName(), 1d - pair.calculateSimilarity());
148 private String getGroupName(URL location){
149 String url = location.toString();
150 if(url.startsWith("jar:")){
151 url = url.substring("jar:".length(), url.lastIndexOf('!'));
156 private void setGroups(){
157 labels = new LabelMap();
158 labels.setGroupEnabled(true);
159 Item[] items = mdspane.getItems();
160 Map<String, BirthmarkSet> map = new HashMap<String, BirthmarkSet>();
161 for(BirthmarkSet s: set) map.put(s.getName(), s);
163 for(Item item: items){
164 BirthmarkSet s = map.get(item.getName());
166 labels.addLabel(s.getName());
167 labels.setGroup(s.getName(), getGroupName(s.getLocation()));
169 item.setGroupId(labels.getGroupIdFromElementName(item.getName()));
174 * This method must called after
175 * {@link #initData(BirthmarkSet[], BirthmarkEnvironment) <code>initData</code>}.
176 * Because this method uses calculated value in initData method.
178 private void initLayouts() throws ResourceNotFoundException{
179 Table<String> table = initData(set, context);
181 final Messages messages = stigmata.getMessages();
182 setting = new MdsGraphSetting();
183 mdspane = new MdsPane(new MdsMethod<String>(table), setting, messages);
184 setting.setShowLabels(true);
187 JCheckBox check = new JCheckBox(stigmata.getMessages().get("showlabel.button.label"), true);
188 check.addActionListener(new ActionListener(){
190 public void actionPerformed(ActionEvent e){
191 JCheckBox c = (JCheckBox)e.getSource();
192 setting.setShowLabels(c.isSelected());
195 Action openSelection = new OpenItemsAction(mdspane, this);
197 Action clusteringAction = new ClusteringAction(mdspane);
199 SaveAction exportMdsImageAction = new SaveAction(stigmata,
200 new MdsImageExporter(mdspane));
201 exportMdsImageAction.setExtensions(stigmata.getMessages().getArray("savemds.extensions"));
202 exportMdsImageAction.setDescrpition(stigmata.getMessages().get("savemds.description"));
204 SaveAction exportItemsAction = new SaveAction(stigmata, new MdsItemsLocationExporter(mdspane));
205 exportItemsAction.setExtensions(stigmata.getMessages().getArray("savelocation.extensions"));
206 exportItemsAction.setDescrpition(stigmata.getMessages().get("savelocation.description"));
208 PopupButton saveButton = new PopupButton(GUIUtility.createButton(messages, "savemds", exportMdsImageAction));
209 saveButton.addMenuItem(GUIUtility.createJMenuItem(messages, "savelocation", exportItemsAction));
211 JLabel numberOfDotsLabel = new JLabel(String.valueOf(set.length));
212 GUIUtility.decorateJComponent(messages, numberOfDotsLabel, "mdsgraph.count");
214 zoomRatio = new JTextField("100%", 5);
215 GUIUtility.decorateJComponent(messages, zoomRatio, "mdszoomratio");
216 zoomRatio.setColumns(5);
217 zoomRatio.addActionListener(new ActionListener(){
219 public void actionPerformed(ActionEvent e){
221 String label = zoomRatio.getText();
222 if(label.endsWith("%")){
223 label = label.substring(0, label.lastIndexOf('%'));
225 label = label.trim();
226 int ratio = Integer.parseInt(label);
227 userInputtedValue = true;
229 } catch(NumberFormatException exception){
230 zoomRatio.setText(mdspane.getZoomRatio() + " %");
234 JComboBox combo = new JComboBox();
235 combo.setRenderer(new ClippedLRListCellRenderer(new Dimension(100, combo.getPreferredSize().height), 50));
236 DrawerFactory factory = DrawerFactory.getInstance();
237 for(Map.Entry<String, Integer> entry: labels.getGroupElementCounts().entrySet()){
238 int groupId = labels.getGroupId(entry.getKey());
239 ClippedLRListCellRenderer.LRItem item = new ClippedLRListCellRenderer.LRItem(entry.getKey(), entry.getValue());
240 item.setIcon(factory.createIcon(groupId));
243 GUIUtility.decorateJComponent(messages, combo, "mdsgraph.group");
245 JToolBar toolbar = new JToolBar();
246 toolbar.add(new ClockwiseRotateAction(mdspane));
247 toolbar.add(new AntiClockwiseRotateAction(mdspane));
248 toolbar.add(new HorizontalFlipAction(mdspane));
249 toolbar.add(new VerticalFlipAction(mdspane));
250 toolbar.add(zoomin = new ZoomInAction(this, this));
251 toolbar.add(zoomout = new ZoomOutAction(this, this));
252 toolbar.add(new ClearAction(mdspane));
254 JPanel south1 = new JPanel(new GridLayout(1, 3));
255 south1.add(numberOfDotsLabel);
256 south1.add(zoomRatio);
259 Box south2 = Box.createHorizontalBox();
260 south2.add(Box.createHorizontalGlue());
261 south2.add(saveButton);
262 south2.add(Box.createHorizontalGlue());
263 south2.add(new JButton(openSelection));
264 south2.add(Box.createHorizontalGlue());
265 south2.add(new JButton(clusteringAction));
266 south2.add(Box.createHorizontalGlue());
268 south2.add(Box.createHorizontalGlue());
270 JPanel south = new JPanel(new GridLayout(2, 1));
274 JPanel center = new JPanel(new FlowLayout(FlowLayout.CENTER));
275 center.addComponentListener(new ComponentAdapter(){
277 public void componentResized(ComponentEvent e){
278 Dimension d = e.getComponent().getSize();
279 mdspane.setSize(d.width - 10, d.height - 10);
282 setLayout(new BorderLayout());
285 JScrollPane scroll = new JScrollPane(center);
286 scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
287 scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
289 add(toolbar, BorderLayout.NORTH);
290 add(scroll, BorderLayout.CENTER);
291 add(south, BorderLayout.SOUTH);