Skip to content

Commit

Permalink
start evolving towwards the next GUI
Browse files Browse the repository at this point in the history
  • Loading branch information
carlosuc3m committed Nov 20, 2024
1 parent 85271d8 commit a7530ee
Show file tree
Hide file tree
Showing 14 changed files with 819 additions and 0 deletions.
180 changes: 180 additions & 0 deletions src/main/java/ai/nets/samj/gui/ButtonIcon.java
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();
}
}
185 changes: 185 additions & 0 deletions src/main/java/ai/nets/samj/gui/Dialog.java
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;'>&nbsp;</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();
}
}
Loading

0 comments on commit a7530ee

Please sign in to comment.