/*
Eteria IRC Client, an RFC 1459 compliant client program written in Java.
Copyright (C) 2000-2001 Javier Kohen <jkohen at tough.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.Enumeration;
import java.net.URL;
import java.net.MalformedURLException;
import ar.com.jkohen.awt.*;
import ar.com.jkohen.awt.event.*;
import ar.com.jkohen.irc.Channel;
import ar.com.jkohen.irc.RFC1459;
import ar.com.jkohen.util.Resources;
import ar.com.jkohen.util.CollatedHashtable;
public class ChatPanelContainer extends Panel implements ActionListener, MouseListener, TextListener
{
private EIRC eirc;
private Resources res;
private CollatedHashtable panels;
private String status_tag;
private String tab_under_menu;
private ChatPanel visible_panel;
private CardLayout container_layout;
private BorderedPanel container;
private ChatTabs tabs;
private PopupMenu tabs_popup;
private MenuItem close_item;
private ImageCanvas label;
private BorderedPanel bottom_panel;
private ImageButton shift_left;
private ImageButton shift_right;
public ChatPanelContainer(EIRC eirc)
{
this.eirc = eirc;
this.panels = new CollatedHashtable(RFC1459.getCollator());
GridBagLayout gb = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
setLayout(gb);
this.container = new BorderedPanel();
gbc.weighty = 1.0;
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridy = 0;
gb.setConstraints(container, gbc);
add(container);
gbc.weightx = 0.0;
gbc.weighty = 0.0;
gbc.gridy = 1;
bottom_panel = new BorderedPanel(res.getString("bottom_panel"));
GridBagLayout bottom_gb = new GridBagLayout();
GridBagConstraints bottom_gbc = new GridBagConstraints();
bottom_panel.setLayout(bottom_gb);
/* Bottom Panel begins here. */
bottom_gbc.anchor = GridBagConstraints.NORTH;
Image i = res.getImage("tabs.logo");
if (i != null)
{
label = new ImageCanvas(i);
bottom_gbc.gridheight = GridBagConstraints.REMAINDER;
bottom_gb.setConstraints(label, bottom_gbc);
bottom_panel.add(label);
bottom_gbc.gridheight = 1;
}
this.tabs = new ChatTabs(eirc);
bottom_gbc.weightx = 1.0;
bottom_gbc.fill = GridBagConstraints.HORIZONTAL;
bottom_gbc.gridheight = GridBagConstraints.REMAINDER;
bottom_gb.setConstraints(tabs, bottom_gbc);
bottom_panel.add(tabs);
bottom_gbc.gridheight = 1;
bottom_gbc.fill = GridBagConstraints.NONE;
bottom_gbc.weightx = 0.0;
this.shift_left = new ImageButton(false);
shift_left.setEnabled(false);
shift_left.setIcon(res.getImage("tabs.icon.shift_left"));
bottom_gb.setConstraints(shift_left, bottom_gbc);
bottom_panel.add(shift_left);
bottom_gbc.gridy = 1;
this.shift_right = new ImageButton(false);
shift_right.setEnabled(false);
shift_right.setIcon(res.getImage("tabs.icon.shift_right"));
bottom_gb.setConstraints(shift_right, bottom_gbc);
bottom_panel.add(shift_right);
/* Bottom Panel ends here. */
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gb.setConstraints(bottom_panel, gbc);
add(bottom_panel);
tabs.setImage(ChatTabs.CHAN, ChatTabs.NORMAL, ChatTabs.LEFT, res.getImage("tabs.normal.chan"));
tabs.setImage(ChatTabs.CHAN, ChatTabs.NORMAL, ChatTabs.CENTER, res.LARGE_NORMAL);
tabs.setImage(ChatTabs.CHAN, ChatTabs.CURRENT, ChatTabs.LEFT, res.getImage("tabs.current.chan"));
tabs.setImage(ChatTabs.CHAN, ChatTabs.CURRENT, ChatTabs.CENTER, res.LARGE_PRESSED);
tabs.setImage(ChatTabs.CHAN, ChatTabs.ALARM, ChatTabs.LEFT, res.getImage("tabs.alarm.chan"));
tabs.setImage(ChatTabs.CHAN, ChatTabs.ALARM, ChatTabs.CENTER, res.LARGE_ALERT);
tabs.setImage(ChatTabs.PRIV, ChatTabs.NORMAL, ChatTabs.LEFT, res.getImage("tabs.normal.private"));
tabs.setImage(ChatTabs.PRIV, ChatTabs.NORMAL, ChatTabs.CENTER, res.LARGE_NORMAL);
tabs.setImage(ChatTabs.PRIV, ChatTabs.CURRENT, ChatTabs.LEFT, res.getImage("tabs.current.private"));
tabs.setImage(ChatTabs.PRIV, ChatTabs.CURRENT, ChatTabs.CENTER, res.LARGE_PRESSED);
tabs.setImage(ChatTabs.PRIV, ChatTabs.ALARM, ChatTabs.LEFT, res.getImage("tabs.alarm.private"));
tabs.setImage(ChatTabs.PRIV, ChatTabs.ALARM, ChatTabs.CENTER, res.LARGE_ALERT);
tabs.setImage(ChatTabs.SERV, ChatTabs.NORMAL, ChatTabs.LEFT, res.getImage("tabs.normal.server"));
tabs.setImage(ChatTabs.SERV, ChatTabs.NORMAL, ChatTabs.CENTER, res.LARGE_NORMAL);
tabs.setImage(ChatTabs.SERV, ChatTabs.CURRENT, ChatTabs.LEFT, res.getImage("tabs.current.server"));
tabs.setImage(ChatTabs.SERV, ChatTabs.CURRENT, ChatTabs.CENTER, res.LARGE_PRESSED);
tabs.setImage(ChatTabs.SERV, ChatTabs.ALARM, ChatTabs.LEFT, res.getImage("tabs.alarm.server"));
tabs.setImage(ChatTabs.SERV, ChatTabs.ALARM, ChatTabs.CENTER, res.LARGE_ALERT);
this.container_layout = new CardLayout();
container.setLayout(container_layout);
this.tabs_popup = new PopupMenu();
add(tabs_popup);
if (label != null)
label.addMouseListener(this);
tabs.addActionListener(this);
tabs.addMouseListener(this);
shift_left.addActionListener(this);
shift_right.addActionListener(this);
tabs_popup.addActionListener(this);
}
private void createMenu(PopupMenu pop, String tag)
{
pop.removeAll();
MenuItem mi = null;
mi = new MenuItem(res.getString("close.privates"));
mi.setActionCommand("close.privates");
pop.add(mi);
mi = new MenuItem(res.getString("close.unread"));
mi.setActionCommand("close.unread");
pop.add(mi);
mi = new MenuItem(res.getString("close.channels"));
mi.setActionCommand("close.channels");
pop.add(mi);
if (tag != null && !tag.equals(status_tag))
{
pop.addSeparator();
/*
mi = new MenuItem(res.getString("open") + " " + tag);
mi.setActionCommand("open");
pop.add(mi);
*/
mi = new MenuItem(res.getString("close") + " " + tag);
mi.setActionCommand("close");
pop.add(mi);
}
}
public void add(ChatPanel cp, String tag)
{
add(cp, tag, false);
}
public void add(ChatPanel cp, String tag, boolean is_status)
{
if (is_status)
{
if (status_tag != null)
{
throw new IllegalArgumentException("already have a status panel");
}
this.status_tag = tag;
}
synchronized (this)
{
panels.put(tag, cp);
container.add(cp, tag.toLowerCase());
tabs.add(tag);
}
updateShiftButtons();
cp.addTextListener(this);
}
public void addPanel(ChatPanel cp, String tag)
{
synchronized (this)
{
panels.put(tag, cp);
container.add(cp, tag.toLowerCase());
}
cp.addTextListener(this);
}
public synchronized void showPanel(String tag)
{
ChatPanel cp = this.visible_panel = (ChatPanel) panels.get(tag);
container_layout.show(container, tag.toLowerCase());
cp.requestFocus();
tabs.notVisible();
container.setTag(cp.getTitle());
}
public void remove(String tag)
{
if (tag.equals(visible_panel))
this.visible_panel = null;
synchronized (this)
{
tabs.remove(tag);
Component c = (Component) panels.remove(tag);
if (c == null) return;
container.remove(c);
if (tag.equals(status_tag))
this.status_tag = null;
String new_tab = tabs.getCurrent();
if (new_tab != null)
{
show(new_tab);
}
else if (panels.containsKey(status_tag))
{
show(status_tag);
}
}
updateShiftButtons();
}
public synchronized void rename(String old_tag, String tag)
{
ChatPanel cp = (ChatPanel) panels.get(old_tag);
// Removing the old panel isn't necessary: adding it under a different tag has the same effect.
container.add(cp, tag.toLowerCase());
if (old_tag.equals(tabs.getVisible()))
container_layout.show(container, tag.toLowerCase());
cp.setPanelTag(tag);
panels.put(tag, cp);
panels.remove(old_tag);
tabs.rename(old_tag, tag);
}
public void setTitle(String tag, String title)
{
ChatPanel cp = (ChatPanel)panels.get(tag);
cp.setTitle(title);
if(this.visible_panel == cp)
container.setTag(title);
}
public synchronized void show(String tag)
{
ChatPanel cp = this.visible_panel = (ChatPanel)panels.get(tag);
container_layout.show(container, tag.toLowerCase());
cp.requestFocus();
cp.setRead(true);
tabs.setAlarm(tag, false);
tabs.makeVisible(tag);
container.setTag(cp.getTitle());
}
private void updateShiftButtons()
{
int tabs_width = tabs.getSize().width;
boolean enabled = tabs_width > 0 && tabs_width < tabs.getPreferredSize().width;
shift_left.setEnabled(enabled);
shift_right.setEnabled(enabled);
}
public ChatPanel getVisible()
{
return visible_panel;
}
public void setFont(Font f)
{
super.setFont(f);
container.setFont(f);
bottom_panel.setFont(f);
tabs.setFont(f);
// Popup menu font
for (int i = 0; i < tabs_popup.getItemCount(); i++)
tabs_popup.getItem(i).setFont(f);
}
public void setForeground(Color c)
{
super.setForeground(c);
container.setForeground(c);
bottom_panel.setForeground(c);
tabs.setForeground(c);
if(label != null)
label.setForeground(c);
}
public void setBackground(Color c)
{
super.setBackground(c);
container.setBackground(c);
bottom_panel.setBackground(c);
tabs.setBackground(c);
if(label != null)
label.setBackground(c);
shift_left.setBackground(c);
shift_right.setBackground(c);
}
public void setBounds(int x, int y, int w, int h)
{
super.setBounds(x, y, w, h);
updateShiftButtons();
}
public void actionPerformed(ActionEvent ev)
{
Object source = ev.getSource();
if (source.equals(tabs))
{
show(ev.getActionCommand());
}
else if (source.equals(shift_left))
{
tabs.shiftLeft();
}
else if (source.equals(shift_right))
{
tabs.shiftRight();
}
else if (source instanceof MenuItem)
{
String cmd = ev.getActionCommand();
if (cmd.equals("open"))
{
show(tab_under_menu);
}
else if (cmd.equals("close"))
{
ChatPanel cp = (ChatPanel) panels.get(tab_under_menu);
if (cp != null)
eirc.close(tab_under_menu);
}
else if (cmd.equals("close.privates"))
{
eirc.closeAllPrivates();
}
else if (cmd.equals("close.unread"))
{
eirc.closeUnreadPrivates();
}
else if (cmd.equals("close.channels"))
{
eirc.closeAllChannels();
}
}
}
public void mouseClicked(MouseEvent ev)
{
}
public void mouseReleased(MouseEvent ev)
{
}
public void mousePressed(MouseEvent ev)
{
Object source = ev.getSource();
if (source.equals(tabs))
{
if (ev.isPopupTrigger() || 0 != (ev.getModifiers() & MouseEvent.BUTTON3_MASK))
{
// WORKAROUND: #27 MSIE doesn't set popupTrigger.
String tab = tabs.getTabAt(ev.getPoint());
tab_under_menu = tab;
createMenu(tabs_popup, tab);
tabs_popup.show(tabs, ev.getX(), ev.getY());
}
}
if (source.equals(label))
{
try
{
eirc.visitURL(new URL(res.getLabel("tabs.url")));
}
catch (MalformedURLException e) {}
}
}
public void mouseEntered(MouseEvent ev)
{
Object source = ev.getSource();
if (source.equals(label))
setCursor(new Cursor(Cursor.HAND_CURSOR));
}
public void mouseExited(MouseEvent ev)
{
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
public void textValueChanged(TextEvent e)
{
ChatPanel cp = (ChatPanel) e.getSource();
String tag = cp.getPanelTag();
// Don't try to set an alarm on a recently closed panel.
synchronized (this)
{
if (panels.containsKey(tag))
{
tabs.setAlarm(tag, true);
cp.setRead(false);
}
}
}
}