// // PrivateContainer.cs // // Author: // Jean-Philippe Bruyère // // Copyright (c) 2015 jp // // 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 3 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, see . using System; using System.Xml.Serialization; using System.ComponentModel; using Cairo; namespace Crow { /// /// Implement drawing and layouting for a single child, but /// does not implement IXmlSerialisation to allow reuse of container /// behaviour for widgets that have other xml hierarchy: example /// TemplatedControl may have 3 children (template,templateItem,content) but /// behave exactely as a container for layouting and drawing /// public class PrivateContainer : GraphicObject { #region CTOR public PrivateContainer() : base() { } public PrivateContainer(Rectangle _bounds) : base(_bounds) { } #endregion protected GraphicObject child; protected virtual T SetChild(T _child) { if (child != null) { child.LayoutChanged -= OnChildLayoutChanges; this.RegisterForLayouting (LayoutingType.Sizing); child.Parent = null; } child = _child as GraphicObject; if (child != null) { child.Parent = this; child.LayoutChanged += OnChildLayoutChanges; child.RegisterForLayouting (LayoutingType.Sizing); } return (T)_child; } #region GraphicObject Overrides public override void ResolveBindings () { base.ResolveBindings (); if (child != null) child.ResolveBindings (); } protected void ResolveBindingsWithNoRecurse () { base.ResolveBindings (); } public override GraphicObject FindByName (string nameToFind) { if (Name == nameToFind) return this; return child == null ? null : child.FindByName (nameToFind); } public override bool Contains (GraphicObject goToFind) { return child == goToFind ? true : child == null ? false : child.Contains(goToFind); } protected override int measureRawSize (LayoutingType lt) { if (child == null) return base.measureRawSize (lt); if (lt == LayoutingType.Width) return child.RegisteredLayoutings.HasFlag(LayoutingType.Width) ? -1 : child.Slot.Size.Width + 2 * Margin; else return child.RegisteredLayoutings.HasFlag(LayoutingType.Height) ? -1 : child.Slot.Size.Height + 2 * Margin; } public override bool UpdateLayout (LayoutingType layoutType) { if (child != null) { //force sizing to fit if sizing on children and //child has stretched size switch (layoutType) { case LayoutingType.Width: if (Width < 0 && child.Width == 0) child.Width = -1; break; case LayoutingType.Height: if (Height < 0 && child.Height == 0) child.Height = -1; break; } } return base.UpdateLayout (layoutType); } public override void OnLayoutChanges (LayoutingType layoutType) { base.OnLayoutChanges (layoutType); switch (layoutType) { case LayoutingType.Width: if (child != null) { child.RegisterForLayouting (LayoutingType.X | LayoutingType.Width); } break; case LayoutingType.Height: if (child != null) { child.RegisterForLayouting (LayoutingType.Y | LayoutingType.Height); } break; } } public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { GraphicObject g = sender as GraphicObject; switch (arg.LayoutType) { case LayoutingType.X: break; case LayoutingType.Y: break; case LayoutingType.Width: if (this.Bounds.Width < 0) this.RegisterForLayouting (LayoutingType.Width); break; case LayoutingType.Height: if (this.Bounds.Height < 0) this.RegisterForLayouting (LayoutingType.Height); break; } } protected override void onDraw (Context gr) { base.onDraw (gr); gr.Save (); //clip to client zone CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius); gr.Clip (); if (child != null) child.Paint (ref gr); gr.Restore (); } protected override void UpdateCache (Context ctx) { //ctx.Save (); Rectangle rb = Slot + Parent.ClientRectangle.Position; using (ImageSurface cache = new ImageSurface (bmp, Format.Argb32, Slot.Width, Slot.Height, 4 * Slot.Width)) { Context gr = new Context (cache); //clip to client zone CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius); gr.Clip (); if (Clipping.count > 0) { Clipping.clearAndClip (gr); if (child != null) { base.onDraw (gr); child.Paint (ref gr); } } gr.Dispose (); ctx.SetSourceSurface (cache, rb.X, rb.Y); ctx.Paint (); } Clipping.Reset(); //ctx.Restore (); } // public override Rectangle ContextCoordinates (Rectangle r) // { // return // Parent.ContextCoordinates(r) + Slot.Position + ClientRectangle.Position; // } // public override void Paint(ref Cairo.Context ctx) // { // if (!Visible)//check if necessary?? // return; // // ctx.Save(); // // base.Paint(ref ctx); // // //clip to client zone // CairoHelpers.CairoRectangle (ctx, Parent.ContextCoordinates(ClientRectangle + Slot.Position), CornerRadius); // ctx.Clip(); // // if (child != null) // child.Paint(ref ctx); // // ctx.Restore(); // } #endregion #region Mouse handling public override void checkHoverWidget (MouseMoveEventArgs e) { base.checkHoverWidget (e); if (child != null) if (child.MouseIsIn (e.Position)) child.checkHoverWidget (e); } #endregion public override void ClearBinding () { if (child != null) child.ClearBinding (); base.ClearBinding (); } } }