-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
start evolving towwards the next GUI
- Loading branch information
1 parent
85271d8
commit a7530ee
Showing
14 changed files
with
819 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
/*- | ||
* #%L | ||
* Library to call models of the family of SAM (Segment Anything Model) from Java | ||
* %% | ||
* Copyright (C) 2024 SAMJ developers. | ||
* %% | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* #L% | ||
*/ | ||
package ai.nets.samj.gui; | ||
|
||
import java.awt.Color; | ||
import java.awt.Dimension; | ||
import java.awt.Image; | ||
import java.io.File; | ||
import java.io.IOException; | ||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.net.URL; | ||
import java.net.URLClassLoader; | ||
import java.security.CodeSource; | ||
import java.security.ProtectionDomain; | ||
|
||
import javax.swing.BorderFactory; | ||
import javax.swing.ImageIcon; | ||
import javax.swing.JButton; | ||
import javax.swing.SwingConstants; | ||
/** | ||
* ButtonIcon class represents a custom JButton with icons for normal and pressed states. | ||
* @author Carlos Garcia | ||
* @author Daniel Sage | ||
*/ | ||
public class ButtonIcon extends JButton { | ||
|
||
/** | ||
* Serial version unique identifier | ||
*/ | ||
private static final long serialVersionUID = 7396676607184967666L; | ||
/** | ||
* Prefix used in the file name of the images that represent that the button is pressed. | ||
*/ | ||
private static final String PRESSED_PREFIX = "pressed_"; | ||
/** | ||
* Icon for when the button is not pressed | ||
*/ | ||
private ImageIcon normalIcon; | ||
/** | ||
* Icon for when the button is pressed | ||
*/ | ||
private ImageIcon pressedIcon; | ||
/** | ||
* String that is displayed inside the button | ||
*/ | ||
private String text; | ||
/** | ||
* Original color of the buttons | ||
*/ | ||
private Color color; | ||
/** | ||
* HTML used to format the button label text. First the color needs to be specified, then the | ||
* text that wants to be in the button | ||
*/ | ||
private static final String BTN_TEXT_HTML = "<html><font color='%s'>%s</font></html>"; | ||
/** | ||
* Color code for the HTML String of the button for when the button is not pressed | ||
*/ | ||
private static final String NOT_PRESSED_COLOR = "black"; | ||
/** | ||
* Color code for the HTML String of the button for when the button is pressed | ||
*/ | ||
private static final String PRESSED_COLOR = "white"; | ||
|
||
/** | ||
* Constructor. Creates a button that has an icon inside. The icon changes when pressed. | ||
* @param text | ||
* the text inside the button | ||
* @param filePath | ||
* the path to the file that contains the image that is going to be used | ||
* @param filename | ||
* the name of the file that is going to be used | ||
*/ | ||
public ButtonIcon(String text, String filePath, String filename) { | ||
super(); | ||
this.text = text; | ||
try { | ||
normalIcon = getIcon(filePath + "/" + filename); | ||
pressedIcon = getIcon(filePath + "/" + PRESSED_PREFIX + filename); | ||
if (normalIcon != null) { | ||
setIcon(normalIcon); | ||
setBorder(BorderFactory.createEtchedBorder()); | ||
setOpaque(false); | ||
setContentAreaFilled(false); | ||
setPreferredSize(new Dimension(24, 24)); | ||
setVerticalTextPosition(SwingConstants.BOTTOM); | ||
setHorizontalTextPosition(SwingConstants.CENTER); | ||
setText(String.format(BTN_TEXT_HTML, NOT_PRESSED_COLOR, text)); | ||
} | ||
if (pressedIcon != null) { | ||
this.setPressedIcon(pressedIcon); | ||
} | ||
} | ||
catch (Exception ex) { | ||
setText(text); | ||
} | ||
color = this.getBackground(); | ||
} | ||
|
||
private ImageIcon getIcon(String path) { | ||
while (path.indexOf("//") != -1) path = path.replace("//", "/"); | ||
URL url = ButtonIcon.class.getClassLoader().getResource(path); | ||
if (url == null) { | ||
File f = findJarFile(ButtonIcon.class); | ||
if (f.getName().endsWith(".jar")) { | ||
try (URLClassLoader clsloader = new URLClassLoader(new URL[]{f.toURI().toURL()})){ | ||
url = clsloader.getResource(path); | ||
} catch (IOException e) { | ||
} | ||
} | ||
} | ||
if (url != null) { | ||
ImageIcon img = new ImageIcon(url) ; | ||
Image image = img.getImage(); | ||
Image scaled = image.getScaledInstance(18, 18, Image.SCALE_SMOOTH); | ||
return new ImageIcon(scaled); | ||
} | ||
return null; | ||
} | ||
|
||
private static File findJarFile(Class<?> clazz) { | ||
ProtectionDomain protectionDomain = clazz.getProtectionDomain(); | ||
if (protectionDomain != null) { | ||
CodeSource codeSource = protectionDomain.getCodeSource(); | ||
if (codeSource != null) { | ||
URL location = codeSource.getLocation(); | ||
if (location != null) { | ||
try { | ||
return new File(URI.create(location.toURI().getSchemeSpecificPart()).getPath()); | ||
} catch (URISyntaxException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
/** | ||
* Set the button as pressed or not pressed, changing the image displayed | ||
* @param isPressed | ||
* whether the button is pressed or not | ||
*/ | ||
public void setPressed(boolean isPressed) { | ||
if (isPressed) { | ||
this.setIcon(pressedIcon); | ||
this.setBackground(Color.BLACK); | ||
this.setOpaque(true); | ||
this.setContentAreaFilled(true); | ||
} else { | ||
this.setIcon(normalIcon); | ||
this.setBackground(color); | ||
this.setOpaque(false); | ||
} | ||
|
||
setText(String.format(BTN_TEXT_HTML, isPressed ? PRESSED_COLOR : NOT_PRESSED_COLOR, text)); | ||
|
||
this.setSelected(isPressed); | ||
this.validate(); | ||
this.repaint(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
package ai.nets.samj.gui; | ||
|
||
import java.awt.BorderLayout; | ||
import java.awt.Dimension; | ||
import java.awt.GridLayout; | ||
import java.awt.event.ActionEvent; | ||
import java.awt.event.ActionListener; | ||
|
||
import javax.swing.BorderFactory; | ||
import javax.swing.JButton; | ||
import javax.swing.JCheckBox; | ||
import javax.swing.JComboBox; | ||
import javax.swing.JDialog; | ||
import javax.swing.JFrame; | ||
import javax.swing.JLabel; | ||
import javax.swing.JPanel; | ||
import javax.swing.JTabbedPane; | ||
import javax.swing.JToolBar; | ||
import javax.swing.SwingConstants; | ||
|
||
|
||
public class Dialog extends JDialog implements ActionListener { | ||
|
||
private int count = 1; | ||
private JCheckBox chkRoiManager = new JCheckBox("Add to RoiManager", true); | ||
private JSwitchButton chkInstant = new JSwitchButton("LIVE", "OFF"); | ||
private GridPanel pn2; | ||
private GridPanel pn3; | ||
private JPanel drawerPanel; | ||
private boolean isDrawerOpen = false; | ||
|
||
private JButton go = new JButton("Go"); | ||
private JButton close = new JButton("Close"); | ||
private JButton help = new JButton("Help"); | ||
private JButton export = new JButton("Export..."); | ||
private JComboBox<String> cmbModels = new JComboBox<String>(); | ||
private JComboBox<String> cmbImages = new JComboBox<String>(); | ||
private JComboBox<String> cmbObjects = new JComboBox<String>(); | ||
private JTabbedPane tab = new JTabbedPane(); | ||
private JButton bnModel = new JButton("▶"); | ||
private JLabel drawerTitle = new JLabel(); | ||
|
||
public Dialog() { | ||
super(new JFrame(), "SAMJ v0.0.1"); | ||
cmbModels.setPreferredSize(new Dimension(200, 24)); | ||
cmbModels.addItem("SAM2 Tiny"); | ||
cmbModels.addItem("Model SAM2 Small"); | ||
|
||
cmbImages.setPreferredSize(new Dimension(200, 20)); | ||
cmbImages.addItem("Title Image — Long title"); | ||
cmbImages.addItem("Image1.tif"); | ||
cmbImages.addItem("Image2.tif"); | ||
|
||
cmbObjects.addItem("Only Largest Object"); | ||
cmbObjects.addItem("All Objects"); | ||
|
||
GridPanel pnm = new GridPanel(false, 2); | ||
pnm.place(0, 0, new JLabel("Instant Annotation")); | ||
pnm.place(1, 0, chkInstant); | ||
|
||
GridPanel pna = new GridPanel(false, 2); | ||
pna.place(0, 0, new JLabel("Selection from ROIManager")); | ||
pna.place(1, 0, new JButton("Batch SAMize")); | ||
|
||
JButton bnImages = new JButton("▶"); | ||
bnImages.setPreferredSize(new Dimension(20, 20)); | ||
GridPanel pn1 = new GridPanel(true, 2); | ||
pn1.place(0, 0, cmbModels); | ||
pn1.place(0, 1, bnModel); | ||
pn1.place(1, 0, cmbImages); | ||
pn1.place(1, 1, bnImages); | ||
pn1.place(2, 0, go); | ||
|
||
pn2 = new GridPanel(true, 2); | ||
tab.addTab("Manual", pnm); | ||
tab.addTab("Preset Prompts", pna); | ||
|
||
cmbObjects.setPreferredSize(new Dimension(200, 24)); | ||
pn3 = new GridPanel(false, 2); | ||
pn3.place(1, 0, 1, 1, chkRoiManager); | ||
pn3.place(2, 0, 1, 1, cmbObjects); | ||
pn3.place(3, 0, 1, 1, export); | ||
|
||
JToolBar pnAction = new JToolBar(); | ||
pnAction.setLayout(new GridLayout(1, 2)); | ||
pnAction.setBorder(BorderFactory.createEtchedBorder()); | ||
pnAction.setFloatable(false); | ||
pnAction.add(help); | ||
pnAction.add(close); | ||
|
||
GridPanel pn = new GridPanel(true, 5); | ||
pn.place(0, 0, 1, 1, pn1); | ||
pn.place(1, 0, 1, 1, tab); | ||
pn.place(2, 0, 1, 1, pn3); | ||
|
||
String text = "<html><div style='text-align: center; font-size: 15px;'>" | ||
+ "<span style='color: black;'>SAM</span>" + "<span style='color: red;'>J</span>"; | ||
JLabel title = new JLabel(text, SwingConstants.CENTER); | ||
|
||
JPanel main = new JPanel(new BorderLayout()); | ||
main.add(title, BorderLayout.NORTH); | ||
main.add(pn, BorderLayout.CENTER); | ||
main.add(pnAction, BorderLayout.SOUTH); | ||
|
||
setLayout(new BorderLayout()); | ||
|
||
JToolBar pnInstallModel = new JToolBar(); | ||
pnInstallModel.setLayout(new GridLayout(1, 2)); | ||
pnInstallModel.setBorder(BorderFactory.createEtchedBorder()); | ||
pnInstallModel.setFloatable(false); | ||
pnInstallModel.add(new JButton("Install")); | ||
pnInstallModel.add(new JButton("Uninstall")); | ||
|
||
drawerPanel = new JPanel(); | ||
drawerPanel.setPreferredSize(new Dimension(200, 300)); | ||
drawerPanel.setLayout(new BorderLayout()); | ||
drawerPanel.setBorder(BorderFactory.createEtchedBorder()); | ||
drawerTitle.setText("<html><div style='text-align: center; font-size: 15px;'> </html>"); | ||
drawerPanel.add(drawerTitle, BorderLayout.NORTH); | ||
drawerPanel.add(pnInstallModel, BorderLayout.SOUTH); | ||
HTMLPane html = new HTMLPane("Arial", "#000", "#CCCCCC", 200, 200); | ||
//html.append("<span style='text-align: center; font-size: 20px;>SAM2 Tiny</span"); | ||
html.append("Model description"); | ||
html.append("Model description"); | ||
html.append("Model description"); | ||
html.append(""); | ||
html.append("i", "Other information"); | ||
html.append("i", "References"); | ||
drawerPanel.add(html, BorderLayout.CENTER); | ||
drawerPanel.setVisible(false); | ||
bnModel.setPreferredSize(new Dimension(20, 20)); | ||
add(main, BorderLayout.CENTER); | ||
pack(); | ||
setVisible(true); | ||
|
||
bnModel.addActionListener(this); | ||
go.addActionListener(this); | ||
help.addActionListener(this); | ||
close.addActionListener(this); | ||
chkRoiManager.setEnabled(false); | ||
chkInstant.setEnabled(false); | ||
pn2.setEnabled(false); | ||
pn3.setEnabled(false); | ||
tab.setEnabled(false); | ||
cmbObjects.setEnabled(false); | ||
export.setEnabled(false); | ||
chkInstant.setSelected(true); | ||
} | ||
|
||
@Override | ||
public void actionPerformed(ActionEvent ev) { | ||
if (ev.getSource() == close) { | ||
dispose(); | ||
} | ||
if (ev.getSource() == bnModel) { | ||
toggleDrawer(); | ||
} | ||
if (ev.getSource() == go) { | ||
chkInstant.setEnabled(true); | ||
chkRoiManager.setEnabled(true); | ||
tab.setEnabled(true); | ||
pn2.setEnabled(true); | ||
pn3.setEnabled(true); | ||
cmbObjects.setEnabled(true); | ||
export.setEnabled(true); | ||
} | ||
} | ||
|
||
private void toggleDrawer() { | ||
if (isDrawerOpen) { | ||
drawerPanel.setVisible(false); | ||
remove(drawerPanel); | ||
setSize(getWidth() - 200, getHeight()); | ||
bnModel.setText("▶"); | ||
} else { | ||
add(drawerPanel, BorderLayout.EAST); | ||
drawerPanel.setVisible(true); | ||
setSize(getWidth() + 200, getHeight()); | ||
bnModel.setText("◀"); | ||
} | ||
isDrawerOpen = !isDrawerOpen; | ||
revalidate(); | ||
repaint(); | ||
} | ||
} |
Oops, something went wrong.