1 /*****************************************************/
2 /* This java file is a part of the */
4 /* - Plouf's Java IRC Client - */
6 /* Copyright (C) 2002 - 2005 Philippe Detournay */
8 /* All contacts : theplouf@yahoo.com */
10 /* PJIRC is free software; you can redistribute */
11 /* it and/or modify it under the terms of the GNU */
12 /* General Public License as published by the */
13 /* Free Software Foundation; version 2 or later of */
16 /* PJIRC is distributed in the hope that it will */
17 /* be useful, but WITHOUT ANY WARRANTY; without */
18 /* even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
20 /* General Public License for more details. */
22 /* You should have received a copy of the GNU */
23 /* General Public License along with PJIRC; if */
24 /* not, write to the Free Software Foundation, */
25 /* Inc., 59 Temple Place, Suite 330, Boston, */
26 /* MA 02111-1307 USA */
28 /*****************************************************/
34 import irc.DefaultSource;
35 import irc.EventDispatcher;
36 import irc.IRCConfiguration;
37 import irc.Interpretor;
42 import irc.StyleContext;
43 import irc.dcc.DCCChat;
44 import irc.dcc.DCCFile;
45 import irc.gui.GUISource;
46 import irc.gui.IRCInterface;
47 import irc.gui.common.DockablePanel;
48 import irc.gui.common.DockablePanelListener;
49 import irc.gui.common.MouseWheelPanelListener;
51 import java.awt.BorderLayout;
52 import java.awt.Color;
53 import java.awt.Component;
54 import java.awt.Container;
55 import java.awt.Dimension;
56 import java.awt.Label;
57 import java.awt.LayoutManager;
58 import java.awt.MenuItem;
59 import java.awt.Panel;
60 import java.awt.PopupMenu;
61 import java.awt.TextField;
62 import java.awt.event.ActionEvent;
63 import java.awt.event.ActionListener;
64 import java.awt.event.MouseEvent;
65 import java.util.Enumeration;
66 import java.util.Hashtable;
71 class MDILayout implements LayoutManager {
72 private Hashtable _components;
75 * Create a new MDILayout
78 _components = new Hashtable();
82 public void addLayoutComponent(String name, Component comp) {
83 _components.put(comp, comp);
86 private Component getVisible(Container parent) {
87 Component[] c = parent.getComponents();
88 for (int i = 0; i < c.length; i++)
95 public void layoutContainer(Container parent) {
96 Component c = getVisible(parent);
99 int w = parent.getSize().width;
100 int h = parent.getSize().height;
101 c.setBounds(0, 0, w, h);
105 public Dimension minimumLayoutSize(Container parent) {
106 return new Dimension(0, 0);
110 public Dimension preferredLayoutSize(Container parent) {
111 Component visible = getVisible(parent);
113 return visible.getPreferredSize();
114 return new Dimension(0, 0);
118 public void removeLayoutComponent(Component comp) {
119 _components.remove(comp);
124 * The multiplie document interface.
126 public class PixxMDIInterface extends IRCInterface implements PixxTaskBarListener, PixxMenuBarListener, ActionListener,
127 MouseWheelPanelListener, BaseAWTSourceListener, DockablePanelListener {
128 private PixxPanel _panel;
129 private PixxMenuBar _menu;
130 private PixxTaskBar _task;
132 private PopupMenu _popMenu;
133 private TextField _nickField;
134 private Hashtable _awt2Dock;
135 private AWTInterpretor _interpretor;
136 private PixxConfiguration _pixxConfiguration;
138 private Hashtable _status;
139 private Hashtable _channels;
140 private Hashtable _queries;
141 private Hashtable _dccChats;
142 private Hashtable _dccFiles;
143 private Hashtable _lists;
144 private DefaultSource _defaultSource;
145 private AWTDefaultSource _awtDefaultSource;
148 * Create a new PixxMDIInterface.
151 * global irc configuration.
154 public PixxMDIInterface(IRCConfiguration config) throws Exception {
162 _ircConfiguration.setGUIInfoString("Pixx's designed interface");
163 _pixxConfiguration = new PixxConfigurationLoader(_ircConfiguration).loadPixxConfiguration();
164 _panel = new PixxPanel(_pixxConfiguration);
165 _defaultSource = null;
166 _task = new PixxTaskBar(_pixxConfiguration);
167 _interpretor = new AWTInterpretor(_pixxConfiguration, this);
168 _awt2Dock = new Hashtable();
169 _popMenu = new PopupMenu();
170 _panel.setLayout(new BorderLayout());
172 _mdi.setLayout(new MDILayout());
173 _mdi.setBackground(Color.white);
175 _popMenu.addActionListener(this);
176 _task.addPixxTaskBarListener(this);
177 _menu = new PixxMenuBar(_pixxConfiguration, true);
178 _menu.addPixxMenuBarListener(this);
179 _panel.add(_menu, BorderLayout.NORTH);
180 _panel.add(_mdi, BorderLayout.CENTER);
181 _nickField = new NonFocusableTextField("");
182 _nickField.addActionListener(this);
183 _nickField.setBackground(_pixxConfiguration.getColor(PixxColorModel.COLOR_WHITE));
185 if (!_pixxConfiguration.getB("nickfield")) {
186 _panel.add(_task, BorderLayout.SOUTH);
188 Panel bottom = new Panel();
189 bottom.setLayout(new BorderLayout());
190 bottom.add(_task, BorderLayout.CENTER);
191 Panel nickConfig = new Panel();
192 nickConfig.setLayout(new BorderLayout());
193 Label label = new Label(_panel.getText(PixxTextProvider.GUI_CHANGE_NICK));
194 label.setBackground(_pixxConfiguration.getColor(PixxColorModel.COLOR_BACK));
195 label.setForeground(_pixxConfiguration.getColor(PixxColorModel.COLOR_WHITE));
196 Panel outerNickLabel = new Panel();
197 outerNickLabel.setLayout(new BorderLayout());
198 outerNickLabel.add(label, BorderLayout.CENTER);
199 outerNickLabel.add(new PixxSeparator(PixxSeparator.BORDER_LEFT), BorderLayout.WEST);
200 outerNickLabel.add(new PixxSeparator(PixxSeparator.BORDER_RIGHT), BorderLayout.EAST);
201 outerNickLabel.add(new PixxSeparator(PixxSeparator.BORDER_UP), BorderLayout.NORTH);
202 outerNickLabel.add(new PixxSeparator(PixxSeparator.BORDER_DOWN), BorderLayout.SOUTH);
204 nickConfig.add(outerNickLabel, BorderLayout.NORTH);
205 nickConfig.add(_nickField, BorderLayout.CENTER);
207 bottom.add(nickConfig, (BorderLayout.EAST));
208 _panel.add(bottom, BorderLayout.SOUTH);
211 _channels = new Hashtable();
212 _queries = new Hashtable();
213 _dccChats = new Hashtable();
214 _dccFiles = new Hashtable();
215 _lists = new Hashtable();
216 _status = new Hashtable();
219 } catch (Exception ex) {
220 ex.printStackTrace();
221 throw new Error(ex.getMessage());
226 public Component getComponent() {
231 public void unload() {
233 _popMenu.removeActionListener(this);
234 _task.removePixxTaskBarListener(this);
235 _menu.removePixxMenuBarListener(this);
236 _nickField.removeActionListener(this);
243 _pixxConfiguration = null;
247 private void addAWTDefault() {
248 if (_defaultSource == null)
250 if (_awtDefaultSource == null) {
251 _awtDefaultSource = new AWTDefaultSource(_pixxConfiguration, _defaultSource);
252 _task.addDefaultSource(_awtDefaultSource, true);
256 private void removeAWTDefault() {
257 if (_awtDefaultSource == null)
259 _task.removeDefaultSource(_awtDefaultSource);
260 _awtDefaultSource.release();
261 _awtDefaultSource = null;
264 private void channelCreated(Channel chan, Boolean bring) {
265 AWTChannel awt = new AWTChannel(_pixxConfiguration, chan);
266 awt.addBaseAWTSourceListener(this);
267 _task.addChannel(awt, bring.booleanValue());
268 _channels.put(chan, awt);
271 private void channelRemoved(Channel chan) {
272 AWTChannel s = (AWTChannel) _channels.get(chan);
273 s.removeBaseAWTSourceListener(this);
274 _task.removeChannel(s);
275 _channels.remove(chan);
278 private void queryCreated(Query query, Boolean bring) {
279 AWTQuery awt = new AWTQuery(_pixxConfiguration, query);
280 awt.addBaseAWTSourceListener(this);
281 _task.addQuery(awt, bring.booleanValue());
282 _queries.put(query, awt);
283 if (!bring.booleanValue())
284 _pixxConfiguration.getIRCConfiguration().getAudioConfiguration().onQuery();
287 private void queryRemoved(Query query) {
288 AWTQuery q = (AWTQuery) _queries.get(query);
289 q.removeBaseAWTSourceListener(this);
290 _task.removeQuery(q);
291 _queries.remove(query);
294 private void statusCreated(Status status, Boolean bring) {
295 AWTStatus awt = new AWTStatus(_pixxConfiguration, status);
296 _task.addStatus(awt, bring.booleanValue());
297 awt.addBaseAWTSourceListener(this);
298 _status.put(status, awt);
301 private void statusRemoved(Status status) {
302 AWTStatus s = (AWTStatus) _status.get(status);
303 s.removeBaseAWTSourceListener(this);
304 _task.removeStatus(s);
305 _status.remove(status);
308 private void chanListCreated(ChanList list, Boolean bring) {
309 AWTChanList cl = new AWTChanList(_pixxConfiguration, list);
310 _task.addChanList(cl, bring.booleanValue());
311 cl.addBaseAWTSourceListener(this);
312 _lists.put(list, cl);
315 private void chanListRemoved(ChanList list) {
316 AWTChanList l = (AWTChanList) _lists.get(list);
317 l.removeBaseAWTSourceListener(this);
318 _task.removeChanList(l);
322 private void DCCChatCreated(DCCChat chat, Boolean bbring) {
323 boolean bring = bbring.booleanValue();
324 AWTDCCChat awt = new AWTDCCChat(_pixxConfiguration, chat);
325 awt.addBaseAWTSourceListener(this);
326 _task.addDCCChat(awt, bring);
327 _dccChats.put(chat, awt);
330 private void DCCChatRemoved(DCCChat chat) {
331 AWTDCCChat c = (AWTDCCChat) _dccChats.get(chat);
332 c.removeBaseAWTSourceListener(this);
333 _task.removeDCCChat(c);
334 _dccChats.remove(chat);
338 * A DCCFile has been created.
343 * true if source should be brang.
345 public void DCCFileCreated(DCCFile file, Boolean bring) {
346 _dccFiles.put(file, new AWTDCCFile(_pixxConfiguration, file));
350 * A DCCFile has been removed.
355 public void DCCFileRemoved(DCCFile file) {
356 AWTDCCFile f = (AWTDCCFile) _dccFiles.get(file);
357 _dccFiles.remove(file);
363 public void sourceCreated(Source source, Boolean bring) {
364 if (source instanceof DefaultSource) {
365 _defaultSource = (DefaultSource) source;
366 if (_pixxConfiguration.getIRCConfiguration().getB("multiserver"))
370 if (source instanceof Channel)
371 channelCreated((Channel) source, bring);
372 if (source instanceof Query)
373 queryCreated((Query) source, bring);
374 if (source instanceof Status) {
375 if (_pixxConfiguration.getB("showstatus"))
376 statusCreated((Status) source, bring);
378 if (source instanceof ChanList)
379 chanListCreated((ChanList) source, bring);
380 if (source instanceof DCCChat)
381 DCCChatCreated((DCCChat) source, bring);
382 if (source instanceof DCCFile)
383 DCCFileCreated((DCCFile) source, bring);
387 public void sourceRemoved(Source source) {
388 if (source instanceof DefaultSource) {
389 _defaultSource = null;
392 if (source instanceof Channel)
393 channelRemoved((Channel) source);
394 if (source instanceof Query)
395 queryRemoved((Query) source);
396 if (source instanceof Status) {
397 if (_pixxConfiguration.getB("showstatus"))
398 statusRemoved((Status) source);
400 if (source instanceof ChanList)
401 chanListRemoved((ChanList) source);
402 if (source instanceof DCCChat)
403 DCCChatRemoved((DCCChat) source);
404 if (source instanceof DCCFile)
405 DCCFileRemoved((DCCFile) source);
409 public void serverCreated(Server s) {
413 public void serverConnected(Server s) {
418 public void serverDisconnected(Server s) {
423 public void serverRemoved(Server s) {
432 * title stle context.
434 public void setTitle(String title, StyleContext context) {
435 _menu.setTitle(title, context);
439 * Set the connected state.
442 * true if connected to server, false otherwise.
444 public void setConnected(boolean b) {
445 _menu.setConnected(b);
448 private void test() {
450 if (_task.getActive() != null) {
451 setTitle(_task.getActive().getTitle(), _task.getActive().getStyleContext());
453 setTitle("", _pixxConfiguration.getIRCConfiguration().getDefaultStyleContext());
456 triggerActiveChanged(_task.getActive());
460 * Get active awt source.
462 * @return the current active awt source.
465 public GUISource getActive() {
466 return _task.getActive();
470 public void setActive(GUISource source) {
471 _task.activate((BaseAWTSource) source);
475 public GUISource getGUISource(Source source) {
476 if (source instanceof DefaultSource)
477 return _awtDefaultSource;
478 if (source instanceof Channel)
479 return (GUISource) _channels.get(source);
480 if (source instanceof Query)
481 return (GUISource) _queries.get(source);
482 if (source instanceof Status)
483 return (GUISource) _status.get(source);
484 if (source instanceof ChanList)
485 return (GUISource) _lists.get(source);
486 if (source instanceof DCCChat)
487 return (GUISource) _dccChats.get(source);
488 if (source instanceof DCCFile)
489 return (GUISource) _dccFiles.get(source);
493 private DockablePanel createSource(BaseAWTSource asource) {
494 DockablePanel source = new DockablePanel(asource, _panel.getColor(PixxPanel.COLOR_BACK));
495 source.addDockablePanelListener(this);
496 source.setClosingBehaviour(DockablePanel.DO_NOTHING_ON_CLOSE);
497 _awt2Dock.put(asource, source);
501 private DockablePanel getSource(BaseAWTSource source) {
502 return (DockablePanel) _awt2Dock.get(source);
505 private void deleteSource(BaseAWTSource source) {
506 DockablePanel panel = getSource(source);
508 panel.removeDockablePanelListener(this);
509 _awt2Dock.remove(source);
513 * Dock the specified source.
516 * the source to be docked.
518 public void dock(BaseAWTSource source) {
519 getSource(source).dock();
520 source.requestFocus();
521 if (_pixxConfiguration.getB("hideundockedsources"))
526 * Undock the specified source.
529 * the source to be undocked.
531 public void undock(BaseAWTSource source) {
532 DockablePanel todock = getSource(source);
533 BaseAWTSource[] srcs = _task.getZOrderedSources();
534 for (int i = 0; i < srcs.length; i++) {
535 DockablePanel dock = getSource(srcs[i]);
536 if ((dock.isDocked()) && (dock != todock)) {
537 _task.activate(srcs[i]);
541 todock.undock(source.getShortTitle());
542 source.requestFocus();
543 if (_pixxConfiguration.getB("hideundockedsources"))
548 * Check whether the given source is docked or not.
551 * the source to be checked.
552 * @return true if the source is docked, false otherwise.
554 public boolean isDocked(BaseAWTSource source) {
555 return getSource(source).isDocked();
559 * Get the interpretor for this interface. Any unrecognized command will be
560 * passed to this interpretor.
562 * @return the interpretor for this interface, or null if no default interface
563 * interpretor should be used.
566 public Interpretor getInterpretor() {
571 * Find the AWTSource relative to the given source.
574 * source to find AWTSource from.
575 * @return AWTSource relative to the given source, or null if not found.
577 public BaseAWTSource findBaseAWTSource(Source src) {
578 Enumeration e = _awt2Dock.keys();
579 while (e.hasMoreElements()) {
580 BaseAWTSource asrc = (BaseAWTSource) e.nextElement();
581 if (asrc.getSource() == src)
588 public void AWTSourceAdded(PixxTaskBar bar, BaseAWTSource asource) {
589 DockablePanel source = createSource(asource);
591 source.setVisible(false);
594 if (_pixxConfiguration.getDockingPolicy(asource.getSource().getType().toLowerCase(java.util.Locale.ENGLISH),
595 asource.getSource().getName().toLowerCase(java.util.Locale.ENGLISH)))
600 public void AWTSourceRemoved(PixxTaskBar bar, BaseAWTSource asource) {
601 DockablePanel source = getSource(asource);
603 deleteSource(asource);
611 public void AWTSourceDesactivated(PixxTaskBar bar, BaseAWTSource asource) {
612 DockablePanel source = getSource(asource);
613 _panel.setBackground(_ircConfiguration.getStyleColors((asource.getStyleContext()))[0]);
614 source.setVisible(false);
620 public void AWTSourceActivated(PixxTaskBar bar, BaseAWTSource asource) {
621 if (asource != null) {
622 DockablePanel source = getSource(asource);
623 source.setVisible(true);
625 source.requestFocus();
632 public void eventOccured(PixxTaskBar bar, BaseAWTSource asource, MouseEvent e) {
633 DockablePanel source = getSource(asource);
634 if (_pixxConfiguration.matchMouseConfiguration("taskbarpopup", e)) {
636 // _selectedSource=asource;
637 bar.activate(asource);
639 _popMenu.removeAll();
640 _popMenu.add(new MenuItem(_panel.getText(PixxTextProvider.GUI_CLOSE)));
642 _popMenu.show(_task, e.getX(), e.getY());
644 source.requestFocus();
648 public void actionPerformed(ActionEvent e) {
649 EventDispatcher.dispatchEventAsync(this, "actionPerformedEff", new Object[] { e });
657 public void actionPerformedEff(ActionEvent e) {
658 if (e.getActionCommand().equals(_panel.getText(PixxTextProvider.GUI_CLOSE))) {
659 // _selectedSource.leave();
661 BaseAWTSource src = _task.getActive();
664 } else if (e.getSource() == _nickField) {
665 BaseAWTSource src = _task.getActive();
668 src.getSource().sendString("/nick " + _nickField.getText());
673 public void connectionClicked(PixxMenuBar bar) {
674 GUISource current = getActiveSource();
677 Server currentServer = current.getSource().getServer();
678 if (currentServer == null)
681 if (currentServer.isConnected())
682 currentServer.disconnect();
684 currentServer.connect();
688 public void chanListClicked(PixxMenuBar bar) {
689 GUISource src = _task.getActive();
692 src.getSource().sendString("/list");
696 public void aboutClicked(PixxMenuBar bar) {
697 _pixxConfiguration.getIRCConfiguration().displayAboutPage();
701 public void helpClicked(PixxMenuBar bar) {
702 IRCConfiguration cfg = _pixxConfiguration.getIRCConfiguration();
703 if (_pixxConfiguration.getS("helppage") != null)
704 cfg.getURLHandler().openURL(_pixxConfiguration.getS("helppage"));
708 public void closeClicked(PixxMenuBar bar) {
709 BaseAWTSource src = _task.getActive();
716 public void dockClicked(PixxMenuBar bar) {
717 BaseAWTSource src = _task.getActive();
727 public void mouseWheelMoved(Integer amount) {
728 BaseAWTSource src = _task.getActive();
731 src.mouseWheelMoved(amount);
734 private void updateConnect() {
735 BaseAWTSource active = _task.getActive();
738 Server currentServer = active.getSource().getServer();
739 setConnected(currentServer.isConnected());
743 * Get the active source, or null if none is active.
745 * @return active source, or null.
747 public GUISource getActiveSource() {
748 return _task.getActive();
752 public void titleChanged(BaseAWTSource source) {
753 if (source != getActive())
755 setTitle(source.getTitle(), source.getStyleContext());
759 public void eventOccured(BaseAWTSource source) {
763 public void DockablePanelWindowClosing(DockablePanel panel) {
764 BaseAWTSource source;
765 Enumeration e = _awt2Dock.keys();
766 while (e.hasMoreElements()) {
767 source = (BaseAWTSource) e.nextElement();
768 if (_awt2Dock.get(source) == panel) {
769 if (_pixxConfiguration.getB("leaveonundockedwindowclose"))
779 public void DockablePanelWindowClosed(DockablePanel panel) {