mirror of
https://github.com/Ryujinx/GtkSharp.git
synced 2024-09-08 16:03:21 +02:00
![Mike Kestner](/assets/img/avatar_default.png)
* gtk/Gtk.metadata : Widget.Events is a Gdk.EventMask, not int * sample/GtkDemo/DemoDrawingArea.cs : remove int casts * sample/Scribble.cs : remove int casts svn path=/trunk/gtk-sharp/; revision=24601
249 lines
7.1 KiB
C#
249 lines
7.1 KiB
C#
//
|
|
// DemoDrawingArea.cs, port of drawingarea.c from gtk-demo
|
|
//
|
|
// Author: Daniel Kornhauser <dkor@alum.mit.edu>
|
|
// Rachel Hestilow <hestilow@ximian.com>
|
|
//
|
|
// Copyright (C) 2003, Ximian Inc.
|
|
//
|
|
|
|
/* Drawing Area
|
|
*
|
|
* GtkDrawingArea is a blank area where you can draw custom displays
|
|
* of various kinds.
|
|
*
|
|
* This demo has two drawing areas. The checkerboard area shows
|
|
* how you can just draw something; all you have to do is write
|
|
* a signal handler for ExposeEvent, as shown here.
|
|
*
|
|
* The "scribble" area is a bit more advanced, and shows how to handle
|
|
* events such as button presses and mouse motion. Click the mouse
|
|
* and drag in the scribble area to draw squiggles. Resize the window
|
|
* to clear the area.
|
|
*/
|
|
|
|
|
|
using System;
|
|
|
|
using Gtk;
|
|
using Gdk;
|
|
|
|
namespace GtkDemo {
|
|
public class DemoDrawingArea
|
|
{
|
|
private Gtk.Window window;
|
|
private static Pixmap pixmap = null;
|
|
private static DrawingArea drawingArea;
|
|
private static DrawingArea drawingArea1;
|
|
|
|
public DemoDrawingArea ()
|
|
{
|
|
window = new Gtk.Window ("Drawing Area");
|
|
window.DeleteEvent += new DeleteEventHandler (WindowDelete);
|
|
window.BorderWidth = 8;
|
|
|
|
VBox vbox = new VBox (false, 8);
|
|
vbox.BorderWidth = 8;
|
|
window.Add (vbox);
|
|
|
|
// Create the checkerboard area
|
|
Label label = new Label(null);
|
|
label.Markup = "<u>Checkerboard pattern</u>";
|
|
vbox.PackStart (label, false, false, 0);
|
|
|
|
Frame frame = new Frame ();
|
|
frame.ShadowType = ShadowType.In;
|
|
vbox.PackStart (frame, true, true, 0);
|
|
|
|
drawingArea = new DrawingArea();
|
|
// set a minimum size
|
|
drawingArea.SetSizeRequest (100,100);
|
|
frame.Add(drawingArea);
|
|
drawingArea.ExposeEvent += new ExposeEventHandler (CheckerboardExpose);
|
|
|
|
// Create the scribble area
|
|
Label label1 = new Label ("<u>Scribble area</u>");
|
|
label1.UseMarkup = true;
|
|
vbox.PackStart (label1, false, false, 0);
|
|
|
|
Frame frame1 = new Frame ();
|
|
frame1.ShadowType = ShadowType.In;
|
|
vbox.PackStart (frame1, true, true, 0);
|
|
|
|
drawingArea1 = new DrawingArea ();
|
|
// set a minimun size
|
|
drawingArea1.SetSizeRequest (100, 100);
|
|
frame1.Add (drawingArea1);
|
|
// Signals used to handle backing pixmap
|
|
drawingArea1.ExposeEvent += new ExposeEventHandler (ScribbleExpose);
|
|
drawingArea1.ConfigureEvent += new ConfigureEventHandler (ScribbleConfigure);
|
|
// Event signals
|
|
drawingArea1.MotionNotifyEvent += new MotionNotifyEventHandler (ScribbleMotionNotify);
|
|
drawingArea1.ButtonPressEvent += new ButtonPressEventHandler (ScribbleButtonPress);
|
|
|
|
// Ask to receive events the drawing area doesn't normally
|
|
// subscribe to
|
|
|
|
drawingArea1.Events = EventMask.LeaveNotifyMask | EventMask.ButtonPressMask |
|
|
EventMask.PointerMotionMask | EventMask.PointerMotionHintMask;
|
|
|
|
window.ShowAll ();
|
|
}
|
|
|
|
private void WindowDelete (object o, DeleteEventArgs args)
|
|
{
|
|
window.Hide ();
|
|
window.Destroy ();
|
|
}
|
|
|
|
private void CheckerboardExpose (object o, ExposeEventArgs args)
|
|
{
|
|
|
|
// Defining the size of the Checks
|
|
const int CheckSize = 10;
|
|
const int Spacing = 2;
|
|
|
|
// Defining the color of the Checks
|
|
int i, j, xcount, ycount;
|
|
Gdk.GC gc, gc1, gc2;
|
|
Gdk.Color color = new Gdk.Color ();
|
|
EventExpose eventExpose = args.Event;
|
|
Gdk.Window window = eventExpose.Window;
|
|
gc1 = new Gdk.GC (window);
|
|
|
|
color.Red = 30000;
|
|
color.Green = 0;
|
|
color.Blue = 30000;
|
|
gc1.RgbFgColor = color;
|
|
|
|
gc2 = new Gdk.GC (window);
|
|
color.Red = 65535;
|
|
color.Green = 65535;
|
|
color.Blue = 65535;
|
|
gc2.RgbFgColor = color;
|
|
|
|
|
|
// Start redrawing the Checkerboard
|
|
xcount = 0;
|
|
i = Spacing;
|
|
while (i < drawingArea.Allocation.Width){
|
|
j = Spacing;
|
|
ycount = xcount % 2; //start with even/odd depending on row
|
|
while (j < drawingArea.Allocation.Height){
|
|
gc = new Gdk.GC (window);
|
|
if (ycount % 2 != 0){
|
|
gc = gc1;}
|
|
else{
|
|
gc = gc2;}
|
|
window.DrawRectangle(gc, true, i, j, CheckSize, CheckSize);
|
|
|
|
j += CheckSize + Spacing;
|
|
++ycount;
|
|
}
|
|
i += CheckSize + Spacing;
|
|
++xcount;
|
|
}
|
|
// return true because we've handled this event, so no
|
|
// further processing is required.
|
|
args.RetVal = true;
|
|
|
|
}
|
|
|
|
private void ScribbleExpose (object o, ExposeEventArgs args)
|
|
{
|
|
// We use the "ForegroundGC" for the widget since it already exists,
|
|
// but honestly any GC would work. The only thing to worry about
|
|
// is whether the GC has an inappropriate clip region set.
|
|
|
|
EventExpose eventExpose = args.Event;
|
|
Gdk.Window window = eventExpose.Window;
|
|
Rectangle area = eventExpose.Area;
|
|
|
|
window.DrawDrawable (drawingArea1.Style.ForegroundGC(StateType.Normal),
|
|
pixmap,
|
|
area.X, area.Y,
|
|
area.X, area.Y,
|
|
area.Width, area.Height);
|
|
args.RetVal = false;
|
|
}
|
|
|
|
// Create a new pixmap of the appropriate size to store our scribbles
|
|
private void ScribbleConfigure (object o, ConfigureEventArgs args)
|
|
{
|
|
EventConfigure eventConfigure = args.Event;
|
|
Gdk.Window window = eventConfigure.Window;
|
|
Rectangle allocation = drawingArea1.Allocation;
|
|
pixmap = new Pixmap (window,
|
|
allocation.Width,
|
|
allocation.Height,
|
|
-1);
|
|
// Initialize the pixmap to white
|
|
pixmap.DrawRectangle (drawingArea1.Style.WhiteGC, true, 0, 0,
|
|
allocation.Width, allocation.Height);
|
|
// We've handled the configure event, no need for further processing.
|
|
args.RetVal = true;
|
|
}
|
|
|
|
private void ScribbleMotionNotify (object o, MotionNotifyEventArgs args)
|
|
{
|
|
|
|
// This call is very important; it requests the next motion event.
|
|
// If you don't call Window.GetPointer() you'll only get
|
|
// a single motion event. The reason is that we specified
|
|
// PointerMotionHintMask in drawingArea1.Events.
|
|
// If we hadn't specified that, we could just use ExposeEvent.x, ExposeEvent.y
|
|
// as the pointer location. But we'd also get deluged in events.
|
|
// By requesting the next event as we handle the current one,
|
|
// we avoid getting a huge number of events faster than we
|
|
// can cope.
|
|
|
|
int x, y;
|
|
ModifierType state;
|
|
EventMotion ev = args.Event;
|
|
Gdk.Window window = ev.Window;
|
|
|
|
if (ev.IsHint) {
|
|
ModifierType s;
|
|
window.GetPointer (out x, out y, out s);
|
|
state = s;
|
|
} else {
|
|
x = (int) ev.X;
|
|
y = (int) ev.Y;
|
|
state = (ModifierType) ev.State;
|
|
}
|
|
|
|
if ((state & ModifierType.Button1Mask) != 0 && pixmap != null)
|
|
DrawBrush (x, y);
|
|
/* We've handled it, stop processing */
|
|
args.RetVal = true;
|
|
}
|
|
|
|
|
|
// Draw a rectangle on the screen
|
|
static void DrawBrush (double x, double y)
|
|
{
|
|
Rectangle update_rect = new Rectangle ();
|
|
update_rect.X = (int) x - 3;
|
|
update_rect.Y = (int) y - 3;
|
|
update_rect.Width = 6;
|
|
update_rect.Height = 6;
|
|
|
|
//Paint to the pixmap, where we store our state
|
|
pixmap.DrawRectangle (drawingArea1.Style.BlackGC, true,
|
|
update_rect.X, update_rect.Y,
|
|
update_rect.Width, update_rect.Height);
|
|
drawingArea1.QueueDrawArea (update_rect.X, update_rect.Y,
|
|
update_rect.Width, update_rect.Height);
|
|
}
|
|
|
|
private void ScribbleButtonPress (object o, ButtonPressEventArgs args)
|
|
{
|
|
EventButton ev = args.Event;
|
|
if (ev.Button == 1 && pixmap != null)
|
|
DrawBrush (ev.X, ev.Y);
|
|
//We've handled the event, stop processing
|
|
args.RetVal = true;
|
|
}
|
|
}
|
|
}
|