123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- /*
- * $Id$
- *
- * Copyright (C) 2004 Todd Berman <tberman@off.net>
- * Copyright (C) 2004 Jeroen Zwartepoorte <jeroen@xs4all.nl>
- * Copyright (C) 2005 John Luke <john.luke@gmail.com>
- *
- * based on work by:
- * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez@gmx.net>
- *
- * 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.
- */
- using System;
- using Gtk;
- namespace Gdl
- {
- /// <summary>
- /// This class represents header part of a DockItem.
- /// It provided buttons for iconifying and closing the DockItem.
- /// In addition it lets the user drag the DockItem.
- /// </summary>
- public class DockItemGrip : Container
- {
- private DockItem item;
- private Gdk.Window titleWindow;
- private Button closeButton;
- private Button iconifyButton;
- private Tooltips tooltips;
- private Gdk.Pixbuf icon = null;
- private string title;
- private Pango.Layout layout = null;
- protected DockItemGrip (IntPtr raw) : base (raw) { }
- protected DockItemGrip ()
- {
- WidgetFlags |= WidgetFlags.NoWindow;
- Widget.PushCompositeChild ();
- closeButton = new Button ();
- Widget.PopCompositeChild ();
- closeButton.WidgetFlags &= ~WidgetFlags.CanFocus;
- closeButton.Parent = this;
- closeButton.Relief = ReliefStyle.None;
- closeButton.Show ();
- Image image = new Image (GdlStock.Close, IconSize.Menu);
- closeButton.Add (image);
- image.Show ();
- closeButton.Clicked += new EventHandler (CloseClicked);
- Widget.PushCompositeChild ();
- iconifyButton = new Button ();
- Widget.PopCompositeChild ();
- iconifyButton.WidgetFlags &= ~WidgetFlags.CanFocus;
- iconifyButton.Parent = this;
- iconifyButton.Relief = ReliefStyle.None;
- iconifyButton.Show ();
- image = new Image (GdlStock.MenuLeft, IconSize.Menu);
- iconifyButton.Add (image);
- image.Show ();
- iconifyButton.Clicked += new EventHandler (IconifyClicked);
- tooltips = new Tooltips ();
- tooltips.SetTip (iconifyButton, "Iconify", "Iconify this dock");
- tooltips.SetTip (closeButton, "Close", "Close this dock");
- }
- public DockItemGrip (DockItem item) : this ()
- {
- if (item == null)
- throw new ArgumentNullException ("item", "A valid DockItem must be given");
- Item = item;
- }
- private Gdk.Pixbuf Icon {
- get {
- if (icon == null && item.StockId != null)
- icon = RenderIcon (item.StockId, IconSize.Menu, "");
- return icon;
- }
- set {
- icon = value;
- QueueDraw ();
- }
- }
- public new DockItem Item {
- get {
- return item;
- }
- set {
- if (item != null)
- item.PropertyChanged -= new PropertyChangedHandler (OnPropertyChanged);
- item = value;
- item.PropertyChanged += new PropertyChangedHandler (OnPropertyChanged);
- if (!item.CantClose)
- closeButton.Show ();
- else
- closeButton.Hide ();
- if (!item.CantIconify)
- iconifyButton.Show ();
- else
- iconifyButton.Hide ();
- icon = null;
- layout = null;
- title = null;
- }
- }
- private Pango.Layout Layout {
- get {
- if (layout == null) {
- layout = CreatePangoLayout (Title);
- layout.SingleParagraphMode = true;
- }
- return layout;
- }
- }
- private string Title {
- get {
- if (title == null) {
- if (item.LongName != null)
- title = item.LongName;
- else
- title = "";
- }
- return title;
- }
- set {
- title = value;
- if (layout != null)
- layout.SetMarkup (Title);
- QueueDraw ();
- }
- }
- private Gdk.Rectangle TitleArea {
- get {
- Gdk.Rectangle area;
- int bw = (int)BorderWidth;
- int height, width;
- area.Width = Allocation.Width - 2 * bw;
- Layout.GetPixelSize (out width, out height);
- height = Math.Max (height, closeButton.Allocation.Height);
- height = Math.Max (height, iconifyButton.Allocation.Height);
- if (closeButton.Visible) {
- area.Width -= closeButton.Allocation.Width;
- }
- if (iconifyButton.Visible) {
- area.Width -= iconifyButton.Allocation.Width;
- }
- area.X = Allocation.X + bw;
- area.Y = Allocation.Y + bw;
- area.Height = height;
- if (Direction == TextDirection.Rtl)
- area.X += (Allocation.Width - 2 * bw) - area.Width;
- return area;
- }
- }
- public Gdk.Window TitleWindow {
- get {
- return titleWindow;
- }
- set {
- titleWindow = value;
- }
- }
- private void OnPropertyChanged (object o, string name)
- {
- switch (name) {
- case "StockId":
- Icon = RenderIcon (item.StockId, IconSize.Menu, "");
- break;
- case "LongName":
- Title = item.LongName;
- break;
- case "Locked":
- case "Behavior":
- bool cursor = false;
- if (item.CantClose || item.Locked) {
- closeButton.Hide ();
- }
- else {
- closeButton.Show ();
- cursor = true;
- }
- if (item.CantIconify || item.Locked) {
- iconifyButton.Hide ();
- }
- else {
- iconifyButton.Show ();
- cursor = true;
- }
- if (!cursor && titleWindow != null)
- titleWindow.Cursor = null;
- break;
- default:
- break;
- }
- }
- protected override void OnDestroyed ()
- {
- if (layout != null)
- layout = null;
- if (icon != null)
- icon = null;
- if (tooltips != null)
- tooltips = null;
- if (item != null) {
- // FIXME: Disconnect future signal handlers for notify.
- }
- item = null;
- base.OnDestroyed ();
- }
- protected override bool OnExposeEvent (Gdk.EventExpose evnt)
- {
- Gdk.Rectangle titleArea = TitleArea;
- Gdk.Rectangle exposeArea;
- if (Icon != null) {
- Gdk.Rectangle pixbufRect;
- pixbufRect.Width = icon.Width;
- pixbufRect.Height = icon.Height;
- if (Direction == TextDirection.Rtl) {
- pixbufRect.X = titleArea.X + titleArea.Width - pixbufRect.Width;
- } else {
- pixbufRect.X = titleArea.X;
- titleArea.X += pixbufRect.Width + 4;
- }
- titleArea.Width -= pixbufRect.Width - 4;
- pixbufRect.Y = titleArea.Y + (titleArea.Height - pixbufRect.Height) / 2;
- if (evnt.Area.Intersect (pixbufRect, out exposeArea)) {
- Gdk.GC gc = Style.BackgroundGC (State);
- GdkWindow.DrawPixbuf (gc, icon, 0, 0, pixbufRect.X,
- pixbufRect.Y, pixbufRect.Width,
- pixbufRect.Height, Gdk.RgbDither.None,
- 0, 0);
- }
- }
- /* TODO this crashs win32 at the moment...
- if (titleArea.Intersect (evnt.Area, out exposeArea)) {
- int width, height, textX, textY;
- Layout.GetPixelSize (out width, out height);
- if (Direction == TextDirection.Rtl)
- textX = titleArea.X + titleArea.Width - width;
- else
- textX = titleArea.X;
- textY = titleArea.Y + (titleArea.Height - height) / 2;
- Style.PaintLayout (Style, GdkWindow, State, true,
- exposeArea, this, null, textX,
- textY, layout);
- }
- */
- return base.OnExposeEvent (evnt);
- }
- private void CloseClicked (object o, EventArgs e)
- {
- item.HideItem ();
- }
- private void IconifyClicked (object o, EventArgs e)
- {
- item.IconifyItem ();
- iconifyButton.InButton = false;
- iconifyButton.Leave ();
- }
- protected override void OnRealized ()
- {
- base.OnRealized ();
- if (titleWindow == null) {
- Gdk.WindowAttr attributes = new Gdk.WindowAttr ();
- Gdk.Rectangle area = TitleArea;
- attributes.X = area.X;
- attributes.Y = area.Y;
- attributes.Width = area.Width;
- attributes.Height = area.Height;
- attributes.WindowType = Gdk.WindowType.Temp;
- attributes.Wclass = Gdk.WindowClass.InputOnly;
- attributes.OverrideRedirect = true;
- attributes.EventMask = (int) (Events |
- Gdk.EventMask.ButtonPressMask |
- Gdk.EventMask.ButtonReleaseMask |
- Gdk.EventMask.ButtonMotionMask);
- titleWindow = new Gdk.Window (ParentWindow, attributes,
- (int) (Gdk.WindowAttributesType.X |
- Gdk.WindowAttributesType.Y |
- Gdk.WindowAttributesType.Noredir));
- titleWindow.UserData = Handle;
- if (item.CantClose || item.CantIconify)
- titleWindow.Cursor = null;
- else
- titleWindow.Cursor = new Gdk.Cursor (Display, Gdk.CursorType.Hand2);
- }
- }
- protected override void OnUnrealized ()
- {
- if (titleWindow != null) {
- titleWindow.UserData = IntPtr.Zero;
- titleWindow.Destroy ();
- titleWindow = null;
- }
- base.OnUnrealized ();
- }
- protected override void OnMapped ()
- {
- base.OnMapped ();
- if (titleWindow != null)
- titleWindow.Show ();
- }
- protected override void OnUnmapped ()
- {
- if (titleWindow != null)
- titleWindow.Hide ();
- base.OnUnmapped ();
- }
- protected override void OnSizeRequested (ref Requisition requisition)
- {
- requisition.Width = (int)BorderWidth * 2;
- requisition.Height = (int)BorderWidth * 2;
- // ensure_title_and_icon_pixbuf (grip);
- int layoutHeight, layoutWidth;
- this.Layout.GetPixelSize (out layoutWidth, out layoutHeight);
- Requisition childReq = closeButton.SizeRequest ();
- requisition.Width += childReq.Width;
- layoutHeight = Math.Max (requisition.Height, childReq.Height);
- childReq = iconifyButton.SizeRequest ();
- requisition.Width += childReq.Width;
- layoutHeight = Math.Max (requisition.Height, childReq.Height);
- requisition.Height = layoutHeight;
- if (Icon != null) {
- requisition.Width += icon.Width + 1;
- requisition.Height = Math.Max (requisition.Height, icon.Height);
- }
- }
- private void EllipsizeLayout (int width)
- {
- // no room to draw anything
- if (width < 1) {
- layout.SetMarkup ("");
- return;
- }
- // plenty of room
- int lw, lh;
- layout.GetPixelSize (out lw, out lh);
- if (width > lw)
- return;
- // not enough room for ...
- int ell_w, ell_h;
- Pango.Layout ell = layout.Copy ();
- ell.SetMarkup ("...");
- ell.GetPixelSize (out ell_w, out ell_h);
- if (width < ell_w) {
- layout.SetMarkup ("");
- return;
- }
- // subtract ellipses width
- width -= ell_w;
- int index, trailing;
- Pango.LayoutLine line = layout.GetLine (0);
- if (line.XToIndex (width * 1024, out index, out trailing)) {
- // Console.WriteLine ("length: {0} index: {1} trailing: {2}", layout.Text.Length, index, trailing);
- // FIXME: breaks on accented chars
- if (index < layout.Text.Length)
- layout.SetMarkup (layout.Text.Substring (0, index) + "...");
- }
- }
- protected override void OnSizeAllocated (Gdk.Rectangle allocation)
- {
- base.OnSizeAllocated (allocation);
- Gdk.Rectangle childAlloc;
- int bw = (int)BorderWidth;
- if (Direction == TextDirection.Rtl)
- childAlloc.X = allocation.X + bw;
- else
- childAlloc.X = allocation.X + allocation.Width - bw;
- childAlloc.Y = allocation.Y + bw;
- Requisition buttonReq = closeButton.SizeRequest ();
- if (Direction != TextDirection.Rtl)
- childAlloc.X -= buttonReq.Width;
- childAlloc.Width = buttonReq.Width;
- childAlloc.Height = buttonReq.Height;
- closeButton.SizeAllocate (childAlloc);
- if (Direction == TextDirection.Rtl)
- childAlloc.X += buttonReq.Width;
- buttonReq = iconifyButton.SizeRequest ();
- if (Direction != TextDirection.Rtl)
- childAlloc.X -= buttonReq.Width;
- childAlloc.Width = buttonReq.Width;
- childAlloc.Height = buttonReq.Height;
- iconifyButton.SizeAllocate (childAlloc);
- if (Direction == TextDirection.Rtl)
- childAlloc.X += buttonReq.Width;
- if (TitleWindow != null) {
- layout.SetMarkup (title);
- Gdk.Rectangle area = TitleArea;
- titleWindow.MoveResize (area.X, area.Y,area.Width, area.Height);
- if (Icon != null)
- area.Width -= icon.Width + 1;
- EllipsizeLayout (area.Width);
- }
- }
- protected override void OnAdded (Widget widget)
- {
- Console.WriteLine ("You can't add a widget to DockItemGrip directly");
- }
- protected override void OnRemoved (Widget widget)
- {
- Console.WriteLine ("You can't remove a widget from DockItemGrip directly");
- }
- protected override void ForAll (bool include_internals, Callback cb)
- {
- if (include_internals) {
- cb (closeButton);
- cb (iconifyButton);
- }
- }
- }
- }
|