/*
*/
/**
*
* @author Sebastien Riou
*/
package uk.co.nimp.scardterminalmanager;
import java.awt.event.MouseEvent;
import javax.swing.event.DocumentEvent;
import uk.co.nimp.scardterminalmanager.TerminalInfo;
import code.from.internet.CloseableTabbedPane;
import com.atolsystems.atolutilities.LoggingWindow;
import java.awt.Color;
import java.awt.Component;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.smartcardio.CardException;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.DocumentListener;
public class LogTabbedPane extends CloseableTabbedPane {
final static public String ABSENT_MARK = "(absent) ";
final static public String TERMINAL_PRESENT_PROPERTY = "terminalPresent";
final static public String CARD_CONNECTED_PROPERTY = "cardConnected";
final static public String SELECTED_TERMINAL_PROPERTY = "selectedTerminal";
protected boolean terminalPresent;
TerminalInfo activeTerminal;
protected List<TabHighlighter> tabHighlighters;
public LogTabbedPane(int horizontalTextPosition) {
super(horizontalTextPosition);
init();
}
public LogTabbedPane() {
init();
}
void init() {
tabHighlighters = new LinkedList<TabHighlighter>();
}
/**
* get the index of the first tab with the specified title
* @param title
* @param offset
* @return
*/
public int getFistTabIndex(String title, int offset) {
int out = -1;
for (int i = offset; i < this.getTabCount(); i++) {
if (title.equals(this.getTitleAt(i))) {
out = i;
break;
}
}
return out;
}
int getTerminalTabIndex(TerminalInfo tI) {
int out = -1;
for (int i = 1; i < this.getTabCount(); i++) {
TerminalLoggingWindow log = (TerminalLoggingWindow) this.getTerminalLoggingWindowAt(i);
if (log.gettI() == tI) {
out = i;
break;
}
}
return out;
}
int getTerminalTabIndex(String terminalName) {
int out = -1;
for (int i = 1; i < this.getTabCount(); i++) {
TerminalLoggingWindow log = (TerminalLoggingWindow) this.getTerminalLoggingWindowAt(i);
if (log.gettI().getTerminal().getName().equals(terminalName)) {
out = i;
break;
}
}
return out;
}
TerminalLoggingWindow getTerminalTab(String terminalName) {
TerminalLoggingWindow out = null;
for (int i = 1; i < this.getTabCount(); i++) {
TerminalLoggingWindow log = (TerminalLoggingWindow) this.getTerminalLoggingWindowAt(i);
if (log.gettI().getTerminal().getName().equals(terminalName)) {
out = log;
break;
}
}
return out;
}
public void updateTab(TerminalInfo tI) throws IOException {
int tabIndex = this.getTerminalTabIndex(tI);
TerminalLoggingWindow log = this.getTerminalLoggingWindowAt(tabIndex);
if (tI.isPresent()) {
this.setTitleAt(tabIndex, tI.getTerminal().getName());
log.monitorStream();
/*if (this.getSelectedIndex() == tabIndex) {
updateTerminalPresent(log);
}*/
} else {
/*if (this.getSelectedIndex() == tabIndex) {
updateTerminalPresent(log);
}*/
this.setTitleAt(tabIndex, ABSENT_MARK + tI.getTerminal().getName());
log.logAbsence();
log.stopMonitoring();
try {
tI.getTerminal().disconnect();
} catch (CardException ex) {
Logger.getLogger(LogTabbedPane.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public void setSelectedComponent(Component c) {
TerminalInfo old=activeTerminal;
super.setSelectedComponent(c);
JScrollPane scroll = (JScrollPane) c;
Component child = scroll.getViewport().getComponents()[0];
if (child instanceof TerminalLoggingWindow) {
//updateTerminalPresent((TerminalLoggingWindow) child);
activeTerminal=((TerminalLoggingWindow) child).gettI();
} else {
//updateTerminalPresent(null);
activeTerminal=null;
}
this.firePropertyChange(SELECTED_TERMINAL_PROPERTY, old, activeTerminal);
}
@Override
public void setSelectedIndex(int index) {
TerminalInfo old=activeTerminal;
super.setSelectedIndex(index);
TerminalLoggingWindow log=this.getTerminalLoggingWindowAt(index);
if (null == log) {
activeTerminal=null;
} else {
activeTerminal=log.gettI();
}
this.firePropertyChange(SELECTED_TERMINAL_PROPERTY, old, activeTerminal);
//updateTerminalPresent(log);
}
/**
* must be call only with log==getSelectedComponent
* @param index
*/
/* private void updateTerminalPresent(TerminalLoggingWindow log) {
boolean old = terminalPresent;
if (null == log) {
terminalPresent = false;
} else {
terminalPresent = log.gettI().present;
}
this.firePropertyChange(TERMINAL_PRESENT_PROPERTY, old, terminalPresent);
}*/
@Override
public void addTab(String title, Component component) {
addTab(title, component, null);
}
@Override
public void addTab(String title, Component component, Icon extraIcon) {
javax.swing.JScrollPane jScrollPane = new javax.swing.JScrollPane();
jScrollPane.setViewportView(component);
try {
Object prop = null;
if ((prop = ((JComponent) component).getClientProperty("isClosable")) != null) {
jScrollPane.putClientProperty("isClosable", prop);
}
} catch (Exception ignored) {/*Could probably be a ClassCastException*/
}
super.addTab(title, jScrollPane, extraIcon);
}
TerminalLoggingWindow getSelectedTerminalLoggingWindow() {
javax.swing.JScrollPane scroll = (JScrollPane) this.getSelectedComponent();
Component c = scroll.getViewport().getComponents()[0];
if (c instanceof TerminalLoggingWindow) {
return (TerminalLoggingWindow) c;
}
return null;
}
LoggingWindow getSelectedLoggingWindow() {
javax.swing.JScrollPane scroll = (JScrollPane) this.getSelectedComponent();
Component c = scroll.getViewport().getComponents()[0];
if (c instanceof LoggingWindow) {
return (LoggingWindow) c;
}
return null;
}
TerminalLoggingWindow getTerminalLoggingWindowAt(int index) {
javax.swing.JScrollPane scroll = (JScrollPane) this.getComponentAt(index);
Component c = scroll.getViewport().getComponents()[0];
if (c instanceof TerminalLoggingWindow) {
return (TerminalLoggingWindow) c;
}
return null;
}
protected class TabHighlighter implements DocumentListener, javax.swing.event.ChangeListener, java.awt.event.MouseListener {
final Color originalColor;
final Color highlightColor;
final Component component;
final boolean insert;
final boolean remove;
final boolean change;
public TabHighlighter(Component component, Color color, boolean insert,boolean remove,boolean update ) {
this.component = component;
this.highlightColor = color;
int index = LogTabbedPane.this.indexOfComponent(component);
originalColor=LogTabbedPane.this.getBackgroundAt(index);
LogTabbedPane.this.addChangeListener(this);
LogTabbedPane.this.addMouseListener(this);
this.insert = insert;
this.remove = remove;
this.change = update;
}
public void highlight(){
int index = LogTabbedPane.this.indexOfComponent(component);
LogTabbedPane.this.setBackgroundAt(index, highlightColor);
}
public void insertUpdate(DocumentEvent e) {
if(insert)
highlight();
}
public void removeUpdate(DocumentEvent e) {
if(remove)
highlight();
}
public void changedUpdate(DocumentEvent e) {
if(change)
highlight();
}
public void clearHighlight(){
if(LogTabbedPane.this.indexOfComponent(component)==LogTabbedPane.this.getSelectedIndex())
LogTabbedPane.this.setBackgroundAt(LogTabbedPane.this.getSelectedIndex(), originalColor);
}
public void stateChanged(ChangeEvent e) {
clearHighlight();
}
public void mouseClicked(MouseEvent e) {
clearHighlight();
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
}
void enableHighlightOnChange(int index, Color color) {
enableHighlightOnChange(index, color, true,true,true);
}
void enableHighlightOnChange(int index, Color color, boolean insert,boolean remove,boolean update) {
javax.swing.JScrollPane scroll = (JScrollPane) this.getComponentAt(index);
Component c = scroll.getViewport().getComponents()[0];
if (c instanceof LoggingWindow) {
LoggingWindow log = (LoggingWindow) c;
TabHighlighter th = new TabHighlighter(scroll, color, insert,remove,update);
tabHighlighters.add(th);
log.addDocumentListener(th);
} else {
throw new RuntimeException("not implemented yet");
}
}
void clearHighlight(int index){
javax.swing.JScrollPane scroll = (JScrollPane) this.getComponentAt(index);
Component c = scroll.getViewport().getComponents()[0];
if (c instanceof LoggingWindow) {
LoggingWindow log = (LoggingWindow) c;
for (TabHighlighter th : tabHighlighters) {
if (th.component == this.getComponentAt(index)) {
th.clearHighlight();
break;
}
}
} else {
throw new RuntimeException("not implemented yet");
}
}
void clearHighlightOfSelectedTab() {
clearHighlight(this.getSelectedIndex());
}
void disableHighlightOnChange(int index) {
javax.swing.JScrollPane scroll = (JScrollPane) this.getComponentAt(index);
Component c = scroll.getViewport().getComponents()[0];
if (c instanceof LoggingWindow) {
LoggingWindow log = (LoggingWindow) c;
for (TabHighlighter th : tabHighlighters) {
if (th.component == this.getComponentAt(index)) {
log.removeDocumentListener(th);
tabHighlighters.remove(th);
this.removeChangeListener(th);
break;
}
}
} else {
throw new RuntimeException("not implemented yet");
}
}
int getTabIndex(String title) {
int out = -1;
for (int i = 1; i < this.getTabCount(); i++) {
if (this.getTitleAt(i).equals(title)) {
out = i;
break;
}
}
return out;
}
protected static final long THREAD_JOIN_TIMEOUT = 1000;//in ms
@Override
public void removeTabAt(int index) {
TerminalLoggingWindow log = this.getTerminalLoggingWindowAt(index);
TerminalInfo tI = log.gettI();
Thread workingThread=tI.getWorkingThread();
if (null != workingThread) {
workingThread.interrupt();
long start = System.nanoTime();
do {
try {
workingThread.join(THREAD_JOIN_TIMEOUT);
} catch (InterruptedException ex) {
//do nothing
}
} while (System.nanoTime() - start < THREAD_JOIN_TIMEOUT * 1000000);
if (null != workingThread) {
if (workingThread.isAlive()) {
RuntimeException ex = new RuntimeException("Worker thread for " + tI.getTerminal().getName() + "terminal is not responding");
Logger.getLogger(LogTabbedPane.class.getName()).log(Level.SEVERE, null, ex);
}
workingThread = null;
}
}
try {
log.getTerminal().disconnect();
} catch (CardException ex) {
Logger.getLogger(LogTabbedPane.class.getName()).log(Level.SEVERE, null, ex);
}
log.stopMonitoring();
super.removeTabAt(index);
}
}