1 /*****************************************************/
\r
2 /* This java file is a part of the */
\r
4 /* - Plouf's Java IRC Client - */
\r
6 /* Copyright (C) 2002 - 2005 Philippe Detournay */
\r
8 /* All contacts : theplouf@yahoo.com */
\r
10 /* PJIRC is free software; you can redistribute */
\r
11 /* it and/or modify it under the terms of the GNU */
\r
12 /* General Public License as published by the */
\r
13 /* Free Software Foundation; version 2 or later of */
\r
16 /* PJIRC is distributed in the hope that it will */
\r
17 /* be useful, but WITHOUT ANY WARRANTY; without */
\r
18 /* even the implied warranty of MERCHANTABILITY or */
\r
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
\r
20 /* General Public License for more details. */
\r
22 /* You should have received a copy of the GNU */
\r
23 /* General Public License along with PJIRC; if */
\r
24 /* not, write to the Free Software Foundation, */
\r
25 /* Inc., 59 Temple Place, Suite 330, Boston, */
\r
26 /* MA 02111-1307 USA */
\r
28 /*****************************************************/
\r
30 package irc.gui.pixx;
\r
32 import irc.EventDispatcher;
\r
33 import irc.ListenerGroup;
\r
35 import java.awt.Color;
\r
36 import java.awt.Cursor;
\r
37 import java.awt.Dimension;
\r
38 import java.awt.Font;
\r
39 import java.awt.Graphics;
\r
40 import java.awt.Image;
\r
41 import java.awt.event.InputEvent;
\r
42 import java.awt.event.MouseEvent;
\r
43 import java.awt.event.MouseListener;
\r
44 import java.awt.event.MouseMotionListener;
\r
45 import java.util.Enumeration;
\r
46 import java.util.Vector;
\r
53 * Create a new TaskBarItem
\r
60 * if should be brang.
\r
62 public TaskBarItem(BaseAWTSource src, int arow, boolean abring) {
\r
64 eventWaiting = false;
\r
73 public BaseAWTSource source;
\r
79 * True if some event is waiting.
\r
81 public boolean eventWaiting;
\r
83 * True if source must be brang.
\r
85 public boolean bring;
\r
91 * True if source is visible in the taskbar.
\r
93 public boolean visible;
\r
99 public class PixxTaskBar extends PixxPanel implements MouseListener, MouseMotionListener, BaseAWTSourceListener {
\r
100 private final ListenerGroup _listeners;
\r
102 private TaskBarItem _active;
\r
103 private TaskBarItem _pressed;
\r
104 private final Vector _items;
\r
106 private final int[] _itemCount;
\r
107 private final int[] _visibleItemCount;
\r
108 private final Font _font;
\r
109 private Image _buffer;
\r
110 private int _iwidth;
\r
111 private int _ileft;
\r
112 private int _zorder;
\r
113 private boolean _handCursor;
\r
114 private int _overX;
\r
115 private int _overY;
\r
116 private final int _maxWidth;
\r
119 * Create a new PixxTaskBar.
\r
122 * global irc configuration.
\r
124 public PixxTaskBar(PixxConfiguration config) {
\r
126 _font = new Font("", 0, 12);
\r
127 _listeners = new ListenerGroup();
\r
130 _items = new Vector();
\r
131 _itemCount = new int[2];
\r
132 _visibleItemCount = new int[2];
\r
135 _visibleItemCount[0] = 0;
\r
136 _visibleItemCount[1] = 0;
\r
139 _handCursor = false;
\r
144 addMouseListener(this);
\r
145 addMouseMotionListener(this);
\r
146 _maxWidth = config.getI("taskbaritemwidth");
\r
150 public void release() {
\r
152 removeMouseMotionListener(this);
\r
153 removeMouseListener(this);
\r
163 public void addPixxTaskBarListener(PixxTaskBarListener lis) {
\r
164 _listeners.addListener(lis);
\r
168 * Remove a listener.
\r
171 * listener to remove.
\r
173 public void removePixxTaskBarListener(PixxTaskBarListener lis) {
\r
174 _listeners.removeListener(lis);
\r
177 private TaskBarItem findItem(BaseAWTSource source) {
\r
178 if (source == null)
\r
180 for (int i = 0; i < _items.size(); i++)
\r
181 if (((TaskBarItem) _items.elementAt(i)).source == source)
\r
182 return (TaskBarItem) _items.elementAt(i);
\r
186 private void removeFromVector(Vector v, Object o) {
\r
187 for (int i = 0; i < v.size(); i++)
\r
188 if (v.elementAt(i) == o)
\r
189 v.removeElementAt(i);
\r
192 private synchronized void enter(BaseAWTSource source, int row, boolean bring) {
\r
193 TaskBarItem item = new TaskBarItem(source, row, bring);
\r
194 source.addBaseAWTSourceListener(this);
\r
195 _items.insertElementAt(item, _items.size());
\r
197 _visibleItemCount[row]++;
\r
198 _listeners.sendEvent("AWTSourceAdded", this, source);
\r
205 private synchronized void leave(BaseAWTSource source, int row) {
\r
206 TaskBarItem item = findItem(source);
\r
207 source.removeBaseAWTSourceListener(this);
\r
209 _visibleItemCount[row]--;
\r
210 boolean change = getActive() == source;
\r
211 removeFromVector(_items, item);
\r
214 _listeners.sendEvent("AWTSourceRemoved", this, source);
\r
220 * Get icons count in this task bar.
\r
222 * @return icons count.
\r
224 public int getCount() {
\r
225 return _itemCount[0] + _itemCount[1];
\r
229 * Add a new channel in the taskbar.
\r
234 * true if this new channel must be made the active awt source.
\r
236 public void addChannel(AWTChannel chan, boolean bring) {
\r
237 enter(chan, 0, bring);
\r
241 * Remove the given channel from the taskbar.
\r
244 * channel to remove.
\r
246 public void removeChannel(AWTChannel chan) {
\r
251 * Add a new status in the taskbar.
\r
256 * true if this new status must be made the active awt source.
\r
258 public void addStatus(AWTStatus status, boolean bring) {
\r
259 enter(status, 1, bring);
\r
263 * Remove the given status from the taskbar.
\r
266 * status to remove.
\r
268 public void removeStatus(AWTStatus status) {
\r
273 * Add a new default source in the taskbar.
\r
276 * default source to add.
\r
278 * true if this new default source must be made the active awt
\r
281 public void addDefaultSource(AWTDefaultSource source, boolean bring) {
\r
282 enter(source, 1, bring);
\r
286 * Remove the given default source from the taskbar.
\r
289 * default sourceto remove.
\r
291 public void removeDefaultSource(AWTDefaultSource source) {
\r
296 * Add a new query in the taskbar.
\r
301 * true if this new query must be made the active awt source.
\r
303 public void addQuery(AWTQuery query, boolean bring) {
\r
304 enter(query, 1, bring);
\r
308 * Remove the given query from the taskbar.
\r
313 public void removeQuery(AWTQuery query) {
\r
318 * Add a new chanlist in the taskbar.
\r
323 * true if this new chanlist must be made the active awt source.
\r
325 public void addChanList(AWTChanList chanlist, boolean bring) {
\r
326 enter(chanlist, 1, bring);
\r
330 * Remove the given chanlist from the taskbar.
\r
333 * chanlist to remove.
\r
335 public void removeChanList(AWTChanList chanlist) {
\r
336 leave(chanlist, 1);
\r
340 * Add a new dcc chat in the taskbar.
\r
345 * true if this new dcc chat must be made the active awt source.
\r
347 public void addDCCChat(AWTDCCChat chat, boolean bring) {
\r
348 enter(chat, 1, bring);
\r
352 * Remove the given dcc chat from the taskbar.
\r
355 * dcc chat to remove.
\r
357 public void removeDCCChat(AWTDCCChat chat) {
\r
361 private BaseAWTSource findFirst() {
\r
362 TaskBarItem first = null;
\r
364 for (int i = 0; i < _items.size(); i++) {
\r
365 TaskBarItem item = (TaskBarItem) _items.elementAt(i);
\r
366 if (item.zorder > maxz) {
\r
367 maxz = item.zorder;
\r
373 return first.source;
\r
377 * Get all sources sorted by their z-order.
\r
379 * @return z-ordered sources.
\r
381 public BaseAWTSource[] getZOrderedSources() {
\r
382 TaskBarItem[] items = new TaskBarItem[_items.size()];
\r
383 for (int i = 0; i < items.length; i++)
\r
384 items[i] = (TaskBarItem) _items.elementAt(i);
\r
386 for (int i = 0; i < items.length - 1; i++) {
\r
387 TaskBarItem item = items[i];
\r
388 int max = item.zorder;
\r
390 for (int j = i + 1; j < items.length; j++) {
\r
392 if (item.zorder > max) {
\r
397 TaskBarItem tmp = items[i];
\r
398 items[i] = items[maxIndex];
\r
399 items[maxIndex] = tmp;
\r
402 BaseAWTSource[] ans = new BaseAWTSource[items.length];
\r
403 for (int i = 0; i < ans.length; i++)
\r
404 ans[i] = items[i].source;
\r
409 * Make the given source visible in the taskbar.
\r
412 * the source that should be visible.
\r
414 public void show(BaseAWTSource source) {
\r
415 if (source == null)
\r
417 TaskBarItem item = findItem(source);
\r
421 item.visible = true;
\r
422 _visibleItemCount[item.row]++;
\r
429 * Make the given source invisible in the taskbar.
\r
432 * the source that should be invisible.
\r
434 public void hide(BaseAWTSource source) {
\r
435 if (source == null)
\r
437 TaskBarItem item = findItem(source);
\r
441 item.visible = false;
\r
442 _visibleItemCount[item.row]--;
\r
449 * Activate the given source.
\r
452 * the source to activate.
\r
454 public void activate(BaseAWTSource source) {
\r
455 if (source == null)
\r
456 source = findFirst();
\r
457 if (source == null)
\r
459 TaskBarItem item = findItem(source);
\r
460 if (item == _active)
\r
464 if (_active != null)
\r
465 _listeners.sendEvent("AWTSourceDesactivated", this, _active.source);
\r
468 if (_active != null) {
\r
469 _active.zorder = _zorder++;
\r
470 _active.eventWaiting = false;
\r
471 _listeners.sendEvent("AWTSourceActivated", this, _active.source);
\r
473 _listeners.sendEvent("AWTSourceActivated", this, null);
\r
475 source.requestFocus();
\r
481 * Get the current active source.
\r
483 * @return active source, or null if there is no active source.
\r
485 public BaseAWTSource getActive() {
\r
486 if (_active == null)
\r
488 return _active.source;
\r
492 public void paint(Graphics g) {
\r
497 public Dimension getPreferredSize() {
\r
498 return new Dimension(16, 2 * getItemHeight() + 16);
\r
501 private int getItemWidth() {
\r
506 private int getItemHeight() {
\r
507 return _font.getSize() + 4;
\r
510 private synchronized void computeWidth() {
\r
511 int w = getSize().width - 63;
\r
512 int n = Math.max(_visibleItemCount[0], _visibleItemCount[1]);
\r
516 _iwidth = Math.min(_maxWidth, w / n);
\r
518 _iwidth = _maxWidth;
\r
521 private int getX(int col) {
\r
522 return col * (getItemWidth() + 9) + _ileft;
\r
525 private int getCol(int x) {
\r
526 return (x - _ileft) / (9 + getItemWidth());
\r
529 private int getY(int row) {
\r
530 return 4 + (getItemHeight() + 8) * row;
\r
533 private int getRow(int y) {
\r
534 return (y - 4) / (8 + getItemHeight());
\r
537 private void drawItem(Graphics g, int col, int row, Color c, String s) {
\r
540 int w = getItemWidth();
\r
541 int h = getItemHeight();
\r
542 g.setClip(x + 1, y + 1, w - 1, h - 1);
\r
544 g.fillRect(x, y, w, h);
\r
545 g.setColor(getColor(COLOR_BLACK));
\r
546 g.drawRect(x, y, w, h);
\r
547 g.setColor(getColor(COLOR_WHITE));
\r
548 g.drawRect(x + 1, y + 1, w - 2, h - 2);
\r
550 int strw = g.getFontMetrics().stringWidth(s);
\r
551 y -= (h - _font.getSize()) / 2;
\r
552 g.drawString(s, x + (w - strw) / 2, y - 1);
\r
553 g.setClip(0, 0, getSize().width, getSize().height);
\r
556 private void drawItem(Graphics g, TaskBarItem item, int col) {
\r
557 int row = item.row;
\r
558 Color c = getColor(COLOR_FRONT);
\r
559 if ((item == _active) || (item == _pressed))
\r
560 c = getColor(COLOR_SELECTED);
\r
561 if ((item != _active) && (item.eventWaiting))
\r
562 c = getColor(COLOR_EVENT);
\r
563 drawItem(g, col++, row, c, item.source.getShortTitle());
\r
567 public void update(Graphics ug) {
\r
569 int w = getSize().width;
\r
570 int h = getSize().height;
\r
572 if (_buffer != null) {
\r
573 if ((_buffer.getWidth(this) != w) || (_buffer.getHeight(this) != h))
\r
577 if (_buffer == null) {
\r
580 _buffer = createImage(w, h);
\r
581 g = _buffer.getGraphics();
\r
582 } catch (Throwable e) {
\r
586 g.setFont(new Font("", Font.PLAIN, 12));
\r
587 int sw = Math.max(g.getFontMetrics().stringWidth(getText(PixxTextProvider.GUI_PRIVATE)), g.getFontMetrics()
\r
588 .stringWidth(getText(PixxTextProvider.GUI_PUBLIC)));
\r
592 // g.setColor(new Color(0x084079));
\r
593 g.setColor(getColor(COLOR_BACK));
\r
594 g.fillRect(0, 0, w, h);
\r
597 Enumeration el = _items.elements();
\r
598 while (el.hasMoreElements()) {
\r
599 TaskBarItem item = (TaskBarItem) el.nextElement();
\r
600 if (item.visible) {
\r
602 drawItem(g, item, col0++);
\r
604 drawItem(g, item, col1++);
\r
609 // g.setColor(new Color(0x336699));
\r
610 g.setColor(getColor(COLOR_FRONT));
\r
611 g.fillRect(4, 5, sw + 2, h - 9);
\r
613 for (int y = 3; y < h / 4; y++) {
\r
614 g.drawLine(sw + 3 + y, y + 3, sw + 3 + y, h / 2 + 2 - y);
\r
615 g.drawLine(sw + 3 + y, h - 3 - y, sw + 3 + y, h / 2 - 1 + y);
\r
618 // g.setColor(Color.black);
\r
619 g.setColor(getColor(COLOR_BLACK));
\r
620 g.drawLine(4, h / 2 - 1, w - 1, h / 2 - 1);
\r
621 g.drawLine(4, h / 2 + 1, w - 1, h / 2 + 1);
\r
622 // g.setColor(Color.white);
\r
623 g.setColor(getColor(COLOR_WHITE));
\r
624 g.drawLine(4, h / 2, w - 1, h / 2);
\r
626 int y = getY(0) + getItemHeight();
\r
627 y -= (getItemHeight() - _font.getSize()) / 2;
\r
629 g.drawString(getText(PixxTextProvider.GUI_PUBLIC), 8, y + 1);
\r
631 y = getY(1) + getItemHeight();
\r
632 y -= (getItemHeight() - _font.getSize()) / 2;
\r
634 g.drawString(getText(PixxTextProvider.GUI_PRIVATE), 8, y - 4);
\r
636 // g.setColor(Color.black);
\r
637 g.setColor(getColor(COLOR_BLACK));
\r
638 g.drawLine(4, 5, 4, h - 5);
\r
640 g.drawLine(4, 5, sw + 6, 5);
\r
641 g.drawLine(4, h - 5, sw + 6, h - 5);
\r
643 g.drawLine(sw + 6, 5, sw + 3 + h / 4, h / 4 + 2);
\r
644 g.drawLine(sw + 3 + h / 4, h / 4 + 2, sw + 6, h / 2 - 1);
\r
646 g.drawLine(sw + 6, h - 5, sw + 3 + h / 4, h - 1 - h / 4 - 1);
\r
647 g.drawLine(sw + 3 + h / 4, h - h / 4 - 2, sw + 6, h - 3 - h / 2 + 4);
\r
649 // g.setColor(Color.white);
\r
650 g.setColor(getColor(COLOR_WHITE));
\r
651 g.drawLine(5, 6, 5, h - 6);
\r
653 g.drawLine(5, 6, sw + 5, 6);
\r
654 g.drawLine(5, h - 6, sw + 5, h - 6);
\r
656 g.drawLine(sw + 6, 6, sw + 2 + h / 4, h / 4 + 2);
\r
657 g.drawLine(sw + 2 + h / 4, h / 4 + 2, sw + 5, h / 2 - 1);
\r
659 g.drawLine(sw + 6, h - 6, sw + 2 + h / 4, h - 1 - h / 4 - 1);
\r
660 g.drawLine(sw + 2 + h / 4, h - 2 - h / 4, sw + 5, h - 1 - h / 2 + 2);
\r
664 if (_buffer != null)
\r
665 ug.drawImage(_buffer, 0, 0, this);
\r
666 TaskBarItem item = getItemAt(_overX, _overY);
\r
667 if (item != null) {
\r
668 String text = item.source.getShortTitle();
\r
669 int tw = ug.getFontMetrics().stringWidth(text);
\r
670 int x = getX(getCol(_overX)) + (getItemWidth() - tw) / 2 - 2;
\r
671 int y = getY(getRow(_overY)) - (getItemHeight() - _font.getSize()) / 2 - 1;
\r
673 int fh = getItemHeight();
\r
674 if (text.length() > 0) {
\r
675 if (tw >= getItemWidth()) {
\r
677 if (x + tw + 5 >= w)
\r
681 ug.setColor(getAlphaColor(getColor(COLOR_FRONT), 200));
\r
682 ug.fillRect(x, y, tw + 4, fh + 4);
\r
683 ug.setColor(getColor(COLOR_WHITE));
\r
684 ug.drawRect(x, y, tw + 4, fh + 4);
\r
685 ug.drawString(text, x + 2, y + fh);
\r
691 private Color getAlphaColor(Color c, int alpha) {
\r
693 return new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha);
\r
694 } catch (Throwable ex) {
\r
699 private TaskBarItem getItemAt(int x, int y) {
\r
700 int row = getRow(y);
\r
701 int col = getCol(x);
\r
705 if ((x >= getItemWidth()) || (y >= getItemHeight()))
\r
707 if ((x < 0) || (y < 0))
\r
710 int currentcol = 0;
\r
711 Enumeration el = _items.elements();
\r
712 while (el.hasMoreElements()) {
\r
713 TaskBarItem item = (TaskBarItem) el.nextElement();
\r
714 if (item.visible) {
\r
715 if (item.row == row) {
\r
716 if (currentcol == col)
\r
726 public void mouseMoved(MouseEvent e) {
\r
727 TaskBarItem item = getItemAt(e.getX(), e.getY());
\r
728 if (item != null) {
\r
729 if (!_handCursor) {
\r
730 setCursor(new Cursor(Cursor.HAND_CURSOR));
\r
731 _handCursor = true;
\r
735 setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
\r
736 _handCursor = false;
\r
739 TaskBarItem oldItem = getItemAt(_overX, _overY);
\r
740 if (oldItem != item) {
\r
748 public void mouseDragged(MouseEvent e) {
\r
753 public void mouseClicked(MouseEvent e) {
\r
757 public void mouseEntered(MouseEvent e) {
\r
761 public void mouseExited(MouseEvent e) {
\r
766 public void mousePressed(MouseEvent e) {
\r
767 TaskBarItem np = getItemAt(e.getX(), e.getY());
\r
771 if (_pressed != null)
\r
772 _listeners.sendEventAsync("eventOccured", this, _pressed.source, e);
\r
776 public void mouseReleased(MouseEvent e) {
\r
778 TaskBarItem src = getItemAt(e.getX(), e.getY());
\r
780 if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0)
\r
782 EventDispatcher.dispatchEventAsyncAndWaitEx(this, "activate", new Object[] { src.source });
\r
783 } catch (InterruptedException ex) {
\r
784 } catch (Throwable ex) {
\r
792 public void titleChanged(BaseAWTSource source) {
\r
798 public void eventOccured(BaseAWTSource source) {
\r
799 TaskBarItem item = findItem(source);
\r
802 if (item == _active)
\r
804 item.eventWaiting = true;
\r