extern public static int XGetGCValues(IntPtr display, IntPtr gc, uint values_mask, out XGCValues values);
extern public static int XChangeGC(IntPtr display, IntPtr gc, uint values_mask, ref XGCValues values);
/// <summary> /// <para>Constructs a new <see cref="T:Xsharp.Graphics"/> object and /// attaches it to a <see cref="T:Xsharp.Drawable"/> instance.</para> /// </summary> /// /// <param name="drawable"> /// <para>The drawable to attach this graphics context to. If the /// drawable is a widget, the foreground and background colors of the /// graphics object will be initially set to the widget's standard /// foreground and background colors.</para> /// </param> /// /// <exception cref="T:System.ArgumentNullException"> /// <para>Raised if <paramref name="drawable"/> is <see langword="null"/>. /// </para> /// </exception> /// /// <exception cref="T:Xsharp.XInvalidOperationException"> /// <para>Raised if <paramref name="drawable"/> does not support /// output, is disposed, or is the root window.</para> /// </exception> public Graphics(Drawable drawable) { if(drawable == null) { throw new ArgumentNullException("drawable"); } else if(drawable.Kind == DrawableKind.InputOnlyWidget) { throw new XInvalidOperationException (S._("X_GraphicsIsOutputOnly")); } else if(drawable is RootWindow) { throw new XInvalidOperationException (S._("X_NonRootOperation")); } dpy = drawable.dpy; this.drawable = drawable; XGCValues gcValues = new XGCValues(); InputOutputWidget widget = (drawable as InputOutputWidget); DoubleBuffer buffer = (drawable as DoubleBuffer); Bitmap bitmap = (drawable as Bitmap); if(widget != null) { foreground = widget.Foreground; background = widget.Background; } else if(buffer != null) { foreground = buffer.Widget.Foreground; background = buffer.Widget.Background; } else if(bitmap != null) { foreground = new Color(0x00, 0x00, 0x00); background = new Color(0xFF, 0xFF, 0xFF); } else { foreground = new Color (StandardColor.Foreground); background = new Color (StandardColor.Background); } gcValues.foreground = drawable.ToPixel(foreground); gcValues.background = drawable.ToPixel(background); if(drawable is DoubleBuffer) { ((DoubleBuffer)drawable).Start(this); } try { IntPtr display = dpy.Lock(); drawableHandle = drawable.GetGCHandle(); gc = drawable.screen.GetGC(bitmap != null); if(gc == IntPtr.Zero) { // Create a new GC because the cache is empty. gc = Xlib.XCreateGC(display, drawableHandle, (uint)(GCValueMask.GCForeground | GCValueMask.GCBackground), ref gcValues); if(gc == IntPtr.Zero) { Display.OutOfMemory(); } } else { // Reset the cached GC back to the default settings. // Xlib will take care of stripping the list down // to just the changes that need to be applied. gcValues.function = Xsharp.GCFunction.GXcopy; gcValues.plane_mask = ~((XPixel)0); gcValues.line_width = 0; gcValues.line_style = Xsharp.LineStyle.LineSolid; gcValues.cap_style = Xsharp.CapStyle.CapButt; gcValues.join_style = Xsharp.JoinStyle.JoinMiter; gcValues.fill_style = Xsharp.FillStyle.FillSolid; gcValues.fill_rule = Xsharp.FillRule.EvenOddRule; gcValues.arc_mode = Xsharp.ArcMode.ArcPieSlice; gcValues.ts_x_origin = 0; gcValues.ts_y_origin = 0; gcValues.subwindow_mode = Xsharp.SubwindowMode.ClipByChildren; gcValues.graphics_exposures = true; gcValues.clip_x_origin = 0; gcValues.clip_y_origin = 0; gcValues.clip_mask = XPixmap.Zero; gcValues.dash_offset = 0; gcValues.dashes = (sbyte)4; Xlib.XChangeGC(display, gc, (uint)(GCValueMask.GCFunction | GCValueMask.GCPlaneMask | GCValueMask.GCForeground | GCValueMask.GCBackground | GCValueMask.GCLineWidth | GCValueMask.GCLineStyle | GCValueMask.GCCapStyle | GCValueMask.GCJoinStyle | GCValueMask.GCFillStyle | GCValueMask.GCFillRule | GCValueMask.GCTileStipXOrigin | GCValueMask.GCTileStipYOrigin | GCValueMask.GCSubwindowMode | GCValueMask.GCGraphicsExposures | GCValueMask.GCClipXOrigin | GCValueMask.GCClipYOrigin | GCValueMask.GCClipMask | GCValueMask.GCDashOffset | GCValueMask.GCDashList | GCValueMask.GCArcMode), ref gcValues); } int sn = drawable.screen.ScreenNumber; double px, mm; px = (double)Xlib.XDisplayWidth(display, sn); mm = (double)Xlib.XDisplayWidthMM(display, sn); dpiX = (float)((px * 25.4) / mm); px = (double)Xlib.XDisplayHeight(display, sn); mm = (double)Xlib.XDisplayHeightMM(display, sn); dpiY = (float)((px * 25.4) / mm); } finally { dpy.Unlock(); } if(drawable is DoubleBuffer) { ((DoubleBuffer)drawable).ClearAtStart(this); } isDisposed = false; }
extern public static IntPtr XCreateGC(IntPtr display, XDrawable drawable, uint values_mask, ref XGCValues values);
/// <summary> /// <para>Draw a three-dimensional effect.</para> /// </summary> /// /// <param name="x"> /// <para>The X co-ordinate of the top-left point.</para> /// </param> /// /// <param name="y"> /// <para>The Y co-ordinate of the top-left point.</para> /// </param> /// /// <param name="width"> /// <para>The width of the rectangle. The pixel at /// <i>x + width - 1</i> is the right-most side of the rectangle.</para> /// </param> /// /// <param name="height"> /// <para>The height of the rectangle. The pixel at /// <i>y + height - 1</i> is the bottom-most side of the rectangle.</para> /// </param> /// /// <param name="effect"> /// <para>The particular effect to draw.</para> /// </param> /// /// <exception cref="T:Xsharp.XException"> /// <para>One of the co-ordinate or size values is out of range.</para> /// </exception> public void DrawEffect(int x, int y, int width, int height, Effect effect) { if(x < -32768 || x > 32767 || width < 0 || width > 65535 || y < -32768 || y > 32767 || height < 0 || height > 65535) { throw new XException(S._("X_RectCoordRange")); } try { // Lock down the display while we do this. IntPtr display = Lock(); // Get the colors that we need to draw the effect. XPixel topShadow; XPixel topShadowEnhance; XPixel bottomShadow; XPixel bottomShadowEnhance; XPixel background; XPixel trim; if((effect & Effect.ContentColors) != 0) { topShadow = drawable.ToPixel (new Color(StandardColor.ContentTopShadow)); topShadowEnhance = drawable.ToPixel (new Color(StandardColor.ContentTopShadowEnhance)); bottomShadow = drawable.ToPixel (new Color(StandardColor.ContentBottomShadow)); bottomShadowEnhance = drawable.ToPixel(new Color (StandardColor.ContentBottomShadowEnhance)); background = drawable.ToPixel (new Color(StandardColor.ContentBackground)); trim = drawable.ToPixel (new Color(StandardColor.ContentTrim)); } else { topShadow = drawable.ToPixel (new Color(StandardColor.TopShadow)); topShadowEnhance = drawable.ToPixel (new Color(StandardColor.TopShadowEnhance)); bottomShadow = drawable.ToPixel (new Color(StandardColor.BottomShadow)); bottomShadowEnhance = drawable.ToPixel (new Color(StandardColor.BottomShadowEnhance)); background = drawable.ToPixel (new Color(StandardColor.Background)); trim = drawable.ToPixel(new Color(StandardColor.Trim)); } // Save the current GC settings and set things // up for drawing 3D effect lines. XGCValues values = new XGCValues(); Xlib.XGetGCValues(display, gc, (uint)(GCValueMask.GCFunction | GCValueMask.GCForeground | GCValueMask.GCFillStyle | GCValueMask.GCLineWidth | GCValueMask.GCLineStyle | GCValueMask.GCJoinStyle | GCValueMask.GCCapStyle | GCValueMask.GCTileStipXOrigin | GCValueMask.GCTileStipYOrigin), out values); XGCValues newValues = values; newValues.function = Function.GXcopy; newValues.line_width = 1; newValues.line_style = LineStyle.LineSolid; newValues.join_style = JoinStyle.JoinMiter; newValues.cap_style = CapStyle.CapProjecting; newValues.fill_style = FillStyle.FillSolid; Xlib.XChangeGC(display, gc, (uint)(GCValueMask.GCFunction | GCValueMask.GCLineWidth | GCValueMask.GCLineStyle | GCValueMask.GCJoinStyle | GCValueMask.GCCapStyle | GCValueMask.GCFillStyle), ref newValues); // Draw the effect. switch(effect & ~(Effect.ContentColors)) { case Effect.Raised: case Effect.Raised | Effect.DefaultButton: { if((effect & Effect.DefaultButton) != 0) { if(width >= 2 && height >= 2) { Xlib.XSetForeground(display, gc, trim); Xlib.XDrawRectangle (display, drawableHandle, gc, x, y, width - 1, height - 1); } ++x; ++y; width -= 2; height -= 2; } if(width >= 4 && height >= 4) { Xlib.XSetForeground(display, gc, topShadow); Xlib.XDrawLine(display, drawableHandle, gc, x, y, x + width - 1, y); Xlib.XDrawLine(display, drawableHandle, gc, x, y + 1, x, y + height - 2); Xlib.XSetForeground (display, gc, topShadowEnhance); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + 1, x + width - 3, y + 1); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + 2, x + 1, y + height - 3); Xlib.XSetForeground(display, gc, bottomShadow); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + height - 2, x + width - 2, y + height - 2); Xlib.XDrawLine(display, drawableHandle, gc, x + width - 2, y + 1, x + width - 2, y + height - 3); Xlib.XSetForeground (display, gc, bottomShadowEnhance); Xlib.XDrawLine(display, drawableHandle, gc, x, y + height - 1, x + width - 1, y + height - 1); Xlib.XDrawLine(display, drawableHandle, gc, x + width - 1, y, x + width - 1, y + height - 2); } } break; case Effect.Indented: { if(width >= 4 && height >= 4) { Xlib.XSetForeground(display, gc, bottomShadow); Xlib.XDrawLine(display, drawableHandle, gc, x, y, x + width - 2, y); Xlib.XDrawLine(display, drawableHandle, gc, x, y + 1, x, y + height - 2); Xlib.XSetForeground (display, gc, bottomShadowEnhance); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + 1, x + width - 3, y + 1); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + 2, x + 1, y + height - 3); Xlib.XSetForeground(display, gc, topShadow); Xlib.XDrawLine(display, drawableHandle, gc, x, y + height - 1, x + width - 1, y + height - 1); Xlib.XDrawLine(display, drawableHandle, gc, x + width - 1, y, x + width - 1, y + height - 2); Xlib.XSetForeground (display, gc, topShadowEnhance); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + height - 2, x + width - 2, y + height - 2); Xlib.XDrawLine(display, drawableHandle, gc, x + width - 2, y + 1, x + width - 2, y + height - 3); } } break; case Effect.Indented | Effect.DefaultButton: { if(width >= 4 && height >= 4) { Xlib.XSetForeground(display, gc, trim); Xlib.XDrawRectangle (display, drawableHandle, gc, x, y, width - 1, height - 1); Xlib.XSetForeground(display, gc, bottomShadow); Xlib.XDrawRectangle (display, drawableHandle, gc, x + 1, y + 1, width - 3, height - 3); } } break; case Effect.Etched: { if(width >= 4 && height >= 4) { Xlib.XSetForeground(display, gc, bottomShadow); Xlib.XDrawRectangle(display, drawableHandle, gc, x, y, width - 2, height - 2); Xlib.XSetForeground(display, gc, topShadow); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + 1, x + width - 3, y + 1); Xlib.XDrawLine(display, drawableHandle, gc, x + width - 1, y, x + width - 1, y + height - 1); Xlib.XDrawLine(display, drawableHandle, gc, x, y + height - 1, x + width - 2, y + height - 1); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + 2, x + 1, y + height - 3); } } break; case Effect.Horizontal: { if(width > 0 && height >= 2) { y += (height - 2) / 2; Xlib.XSetForeground(display, gc, bottomShadow); Xlib.XDrawLine(display, drawableHandle, gc, x, y, x + width - 1, y); Xlib.XSetForeground(display, gc, topShadow); Xlib.XDrawLine(display, drawableHandle, gc, x, y + 1, x + width - 1, y + 1); } } break; case Effect.Vertical: { if(width >= 2 && height > 0) { x += (width - 2) / 2; Xlib.XSetForeground(display, gc, bottomShadow); Xlib.XDrawLine(display, drawableHandle, gc, x, y, x, y + height - 1); Xlib.XSetForeground(display, gc, topShadow); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y, x + 1, y + height - 1); } } break; case Effect.RadioBlank: { DrawRadio(display, x, y, width, height, topShadow, topShadowEnhance, bottomShadow, bottomShadowEnhance, topShadow, topShadow); } break; case Effect.RadioSelected: { DrawRadio(display, x, y, width, height, topShadow, topShadowEnhance, bottomShadow, bottomShadowEnhance, trim, topShadow); } break; case Effect.RadioDisabled: { DrawRadio(display, x, y, width, height, topShadow, topShadowEnhance, bottomShadow, bottomShadowEnhance, topShadowEnhance, topShadowEnhance); } break; case Effect.RadioSelectedDisabled: { DrawRadio(display, x, y, width, height, topShadow, topShadowEnhance, bottomShadow, bottomShadowEnhance, bottomShadow, topShadowEnhance); } break; case Effect.CheckBlank: { // TODO } break; case Effect.CheckSelected: { // TODO } break; case Effect.CheckDisabled: { // TODO } break; case Effect.CheckSelectedDisabled: { // TODO } break; case Effect.MenuSelected: { // TODO } break; case Effect.MenuSelectedHighlighted: { // TODO } break; case Effect.MenuSelectedDisabled: { // TODO } break; case Effect.CaptionButtonRaised: { if(width >= 4 && height >= 4) { Xlib.XSetForeground(display, gc, topShadow); Xlib.XDrawLine(display, drawableHandle, gc, x, y, x + width - 1, y); Xlib.XDrawLine(display, drawableHandle, gc, x, y + 1, x, y + height - 2); Xlib.XSetForeground(display, gc, bottomShadow); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + height - 2, x + width - 2, y + height - 2); Xlib.XDrawLine(display, drawableHandle, gc, x + width - 2, y + 1, x + width - 2, y + height - 3); Xlib.XSetForeground (display, gc, bottomShadowEnhance); Xlib.XDrawLine(display, drawableHandle, gc, x, y + height - 1, x + width - 1, y + height - 1); Xlib.XDrawLine(display, drawableHandle, gc, x + width - 1, y, x + width - 1, y + height - 2); Xlib.XSetForeground (display, gc, background); Xlib.XFillRectangle(display, drawableHandle, gc, x + 1, y + 1, width - 3, height - 3); } } break; case Effect.CaptionButtonIndented: { if(width >= 4 && height >= 4) { Xlib.XSetForeground(display, gc, bottomShadow); Xlib.XDrawLine(display, drawableHandle, gc, x, y, x + width - 2, y); Xlib.XDrawLine(display, drawableHandle, gc, x, y + 1, x, y + height - 2); Xlib.XSetForeground (display, gc, bottomShadowEnhance); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + 1, x + width - 3, y + 1); Xlib.XDrawLine(display, drawableHandle, gc, x + 1, y + 2, x + 1, y + height - 3); Xlib.XSetForeground(display, gc, topShadow); Xlib.XDrawLine(display, drawableHandle, gc, x, y + height - 1, x + width - 1, y + height - 1); Xlib.XDrawLine(display, drawableHandle, gc, x + width - 1, y, x + width - 1, y + height - 2); Xlib.XSetForeground (display, gc, background); Xlib.XFillRectangle(display, drawableHandle, gc, x + 2, y + 2, width - 3, height - 3); } } break; } // Restore the previous GC settings. Xlib.XChangeGC(display, gc, (uint)(GCValueMask.GCFunction | GCValueMask.GCForeground | GCValueMask.GCFillStyle | GCValueMask.GCLineWidth | GCValueMask.GCLineStyle | GCValueMask.GCJoinStyle | GCValueMask.GCCapStyle | GCValueMask.GCTileStipXOrigin | GCValueMask.GCTileStipYOrigin), ref values); } finally { dpy.Unlock(); } }