Marshal arguments into a DrawContext structure

All Draw methods now take a single argument, DrawContext. This structure
contains properties for all possible Draw methods. Only properties valid
to the current Draw method will be set to non-default values.
This commit is contained in:
Aaron Bockover 2010-11-06 17:12:57 -04:00
Родитель 0cd59b45d0
Коммит 2ba270e4c1
6 изменённых файлов: 247 добавлений и 41 удалений

Просмотреть файл

@ -40,5 +40,6 @@
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="Mono.Cairo" />
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
</ItemGroup>
</Project>

Просмотреть файл

@ -31,22 +31,44 @@ using Cairo;
namespace Maigre
{
public struct DrawContext
{
public string Method { get; private set; }
public Gtk.Style Style { get; private set; }
public Gdk.Window Window { get; private set; }
public Gtk.StateType StateType { get; private set; }
public Gtk.ShadowType ShadowType { get; private set; }
public Gdk.Rectangle Area { get; private set; }
public Gtk.Widget Widget { get; private set; }
public string Detail { get; private set; }
public int X { get; private set; }
public int Y { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; }
public Gtk.Orientation Orientation { get; private set; }
public Gtk.ExpanderStyle ExpanderStyle { get; private set; }
public Pango.Layout Layout { get; private set; }
public bool UseText { get; private set; }
public Gdk.WindowEdge Edge { get; private set; }
public int Step { get; private set; }
public int X1 { get; private set; }
public int X2 { get; private set; }
public int Y1 { get; private set; }
public int Y2 { get; private set; }
public bool Fill { get; private set; }
public Gtk.ArrowType ArrowType { get; private set; }
}
public static class Theme
{
public static void DrawBox (Gtk.Style style, Gdk.Window window,
StateType state_type, ShadowType shadow_type, Gdk.Rectangle area, Widget widget,
string detail, int x, int y, int width, int height)
public static void DrawBox (DrawContext context)
{
var cr = Gdk.CairoHelper.Create (widget.GdkWindow);
switch (detail) {
case "hscrollbar":
case "vscrollbar": cr.Color = new Cairo.Color (1, 0, 0); break;
case "slider": cr.Color = new Cairo.Color (0, 1, 0); break;
case "trough": cr.Color = new Cairo.Color (0, 0, 1); break;
Console.WriteLine ("{0}:{1} ({2})", context.Method, context.Detail, context.Area);
using (var cr = Gdk.CairoHelper.Create (context.Window)) {
cr.Color = new Cairo.Color (0, 1, 1);
cr.Rectangle (context.X, context.Y, context.Width, context.Height);
cr.Fill ();
}
cr.Rectangle (x, y, width, height);
cr.Fill ();
((IDisposable)cr).Dispose ();
}
}
}

Просмотреть файл

@ -26,7 +26,7 @@ for word in open ('/usr/include/gtk-2.0/gtk/gtkstyle.h').read ().split ():
elif arg_type == 'const':
arg_type = 'const %s' % word
else:
methods[-1].append ((arg_type, word))
methods[-1].append ((arg_type, word.replace ('_', '')))
arg_type = None
if end:
vmethod = None
@ -57,6 +57,11 @@ for method in methods:
line_count = 0
arg_index = 0
arg_count = len (method[1:])
args = method[1:]
arg_names = []
for arg in args:
arg_names.append (arg[1])
out.write ('static void\n')
line = 'maigre_style_%s (' % method[0]
for arg in method[1:]:
@ -75,43 +80,66 @@ for method in methods:
out.write ('''{
MaigreMonoBridge *bridge;
MonoMethod *managed_method;
gpointer args[1];
''')
if 'shadowtype' not in arg_names:
out.write (' GtkShadowType shadowtype = GTK_SHADOW_NONE;\n')
if 'x' not in arg_names:
out.write (' gint x = 0;\n')
if 'y' not in arg_names:
out.write (' gint y = 0;\n')
if 'width' not in arg_names:
out.write (' gint width = 0;\n')
if 'height' not in arg_names:
out.write (' gint height = 0;\n')
if 'orientation' not in arg_names:
out.write (' GtkOrientation orientation = GTK_ORIENTATION_HORIZONTAL;\n')
if 'expander_style' not in arg_names:
out.write (' GtkExpanderStyle expander_style = GTK_EXPANDER_COLLAPSED;\n')
if '*layout' not in arg_names:
out.write (' PangoLayout *layout = NULL;\n')
if 'use_text' not in arg_names:
out.write (' gboolean use_text = FALSE;\n')
if 'edge' not in arg_names:
out.write (' GdkWindowEdge edge = GDK_WINDOW_EDGE_NORTH_WEST;\n')
if 'step' not in arg_names:
out.write (' gint step = 0;\n')
if 'x1' not in arg_names:
out.write (' gint x1 = 0;\n')
if 'x2' not in arg_names:
out.write (' gint x2 = 0;\n')
if 'y1' not in arg_names:
out.write (' gint y1 = 0;\n')
if 'y2' not in arg_names:
out.write (' gint y2 = 0;\n')
if 'fill' not in arg_names:
out.write (' gboolean fill = FALSE;\n')
if 'arrow_type' not in arg_names:
out.write (' GtkArrowType arrow_type = GTK_ARROW_UP;\n')
out.write ('''
bridge = maigre_mono_bridge ();
if (!bridge->assemblies_loaded ||
(managed_method = maigre_style_method_map[%d].managed_method) == NULL) {
return;
}
''' % method_index)
{
gpointer args[%d] = {
''' \
% (method_index, len (method[1:])))
arg_index = 0
for arg in method[1:]:
assign = ''
if arg[1][0] == '*':
if arg[0] == 'GdkRectangle':
assign = 'maigre_gdk_rectangle_new (bridge, %s)' % arg[1][1:]
elif arg[0] == 'const gchar':
assign = 'mono_string_new (bridge->domain, %s)' % arg[1][1:]
else:
assign = 'maigre_gobject_new (bridge, %s)' % arg[1][1:]
else:
assign = '&%s' % arg[1]
if arg_index < arg_count - 1:
out.write (' %s,\n' % assign)
else:
out.write (' %s\n' % assign)
arg_index += 1
method_index += 1
out.write (''' };
out.write ('''
args[0] = maigre_draw_context_new (bridge, "%s",
style, window, statetype, shadowtype, area,
widget, detail, x, y, width, height, orientation,
expander_style, layout, use_text, edge, step,
x1, x2, y1, y2, fill, arrow_type);
mono_runtime_invoke (managed_method, NULL, args, NULL);
}
mono_runtime_invoke (managed_method, NULL, args, NULL);
}
''')
''' % method[0])
out.write ('''
static void

Просмотреть файл

@ -25,7 +25,7 @@
// THE SOFTWARE.
#include <string.h>
#include <glib.h>
#include <gtk/gtk.h>
#include "maigre-mono-bridge.h"
@ -71,6 +71,61 @@ maigre_mono_bridge_mono_assembly_loaded (MonoAssembly *assembly, MaigreMonoBridg
bridge->glib_getobject != NULL;
}
static gboolean
maigre_mono_bridge_load_draw_context (MaigreMonoBridge *bridge)
{
// NOTE: these names must be in the same order as their
// corresponding members in the MaigreMonoDrawContext struct
static const gchar *names [] = {
"<Method>k__BackingField",
"<Style>k__BackingField",
"<Window>k__BackingField",
"<StateType>k__BackingField",
"<ShadowType>k__BackingField",
"<Area>k__BackingField",
"<Widget>k__BackingField",
"<Detail>k__BackingField",
"<X>k__BackingField",
"<Y>k__BackingField",
"<Width>k__BackingField",
"<Height>k__BackingField",
"<Orientation>k__BackingField",
"<ExpanderStyle>k__BackingField",
"<Layout>k__BackingField",
"<UseText>k__BackingField",
"<Edge>k__BackingField",
"<Step>k__BackingField",
"<X1>k__BackingField",
"<X2>k__BackingField",
"<Y1>k__BackingField",
"<Y2>k__BackingField",
"<Fill>k__BackingField",
"<ArrowType>k__BackingField",
NULL
};
MonoClass *klass;
gint i;
if ((bridge->draw_context.klass = mono_class_from_name (
bridge->image, "Maigre", "DrawContext")) == NULL) {
g_warning ("Maigre.dll assembly does not contain Maigre.DrawContext");
return FALSE;
}
klass = bridge->draw_context.klass;
for (i = 0; names[i] != NULL; i++) {
MonoClassField **slot = G_STRUCT_MEMBER_P (&bridge->draw_context, i * sizeof (gpointer));
if ((*slot = mono_class_get_field_from_name (klass, names[i])) == NULL) {
g_warning ("Maigre.DrawContext does not have a %s field.", names[i]);
return FALSE;
}
}
return TRUE;
}
MaigreMonoBridge *
maigre_mono_bridge ()
{
@ -106,7 +161,7 @@ maigre_mono_bridge ()
return bridge;
}
bridge->init_success = TRUE;
bridge->init_success = maigre_mono_bridge_load_draw_context (bridge);
return bridge;
}

Просмотреть файл

@ -37,6 +37,36 @@
#include <mono/metadata/object.h>
#include <mono/metadata/debug-helpers.h>
// NOTE: this structure must reflect the fields
// in the Maigre.DrawContext managed structure
typedef struct MaigreMonoDrawContext {
MonoClassField *method;
MonoClassField *style;
MonoClassField *window;
MonoClassField *state_type;
MonoClassField *shadow_type;
MonoClassField *area;
MonoClassField *widget;
MonoClassField *detail;
MonoClassField *x;
MonoClassField *y;
MonoClassField *width;
MonoClassField *height;
MonoClassField *orientation;
MonoClassField *expander_style;
MonoClassField *layout;
MonoClassField *use_text;
MonoClassField *edge;
MonoClassField *step;
MonoClassField *x1;
MonoClassField *x2;
MonoClassField *y1;
MonoClassField *y2;
MonoClassField *fill;
MonoClassField *arrow_type;
MonoClass *klass;
} MaigreMonoDrawContext;
typedef struct MaigreMonoBridge {
gboolean init_success;
gboolean assemblies_loaded;
@ -48,6 +78,8 @@ typedef struct MaigreMonoBridge {
MonoMethod *gdk_rectangle_ctor;
MonoMethod *glib_getobject;
MaigreMonoDrawContext draw_context;
} MaigreMonoBridge;
MaigreMonoBridge *maigre_mono_bridge ();

Просмотреть файл

@ -27,6 +27,74 @@
#include "maigre-style.h"
#include "maigre-mono-bridge.h"
static MonoObject *
maigre_draw_context_new (MaigreMonoBridge *bridge, const gchar *method,
GtkStyle *style, GdkWindow *window, GtkStateType state_type,
GtkShadowType shadow_type, GdkRectangle *area, GtkWidget *widget,
const gchar *detail, gint x, gint y, gint width, gint height,
GtkOrientation orientation, GtkExpanderStyle expander_style,
PangoLayout *layout, gboolean use_text, GdkWindowEdge edge, gint step,
gint x1, gint x2, gint y1, gint y2, gboolean fill, GtkArrowType arrow_type)
{
MonoObject *context = mono_object_new (bridge->domain, bridge->draw_context.klass);
if (method != NULL) {
mono_field_set_value (context, bridge->draw_context.method,
mono_string_new (bridge->domain, method));
}
if (style != NULL) {
mono_field_set_value (context, bridge->draw_context.style,
maigre_gobject_new (bridge, style));
}
if (window != NULL) {
mono_field_set_value (context, bridge->draw_context.window,
maigre_gobject_new (bridge, window));
}
if (area != NULL) {
mono_field_set_value (context, bridge->draw_context.area,
maigre_gdk_rectangle_new (bridge, area));
}
if (widget != NULL) {
mono_field_set_value (context, bridge->draw_context.widget,
maigre_gobject_new (bridge, widget));
}
if (detail != NULL) {
mono_field_set_value (context, bridge->draw_context.detail,
mono_string_new (bridge->domain, detail));
}
mono_field_set_value (context, bridge->draw_context.state_type, &state_type);
mono_field_set_value (context, bridge->draw_context.shadow_type, &shadow_type);
mono_field_set_value (context, bridge->draw_context.x, &x);
mono_field_set_value (context, bridge->draw_context.y, &y);
mono_field_set_value (context, bridge->draw_context.width, &width);
mono_field_set_value (context, bridge->draw_context.height, &height);
mono_field_set_value (context, bridge->draw_context.orientation, &orientation);
mono_field_set_value (context, bridge->draw_context.expander_style, &expander_style);
if (layout != NULL) {
mono_field_set_value (context, bridge->draw_context.layout,
maigre_gobject_new (bridge, layout));
}
mono_field_set_value (context, bridge->draw_context.use_text, &use_text);
mono_field_set_value (context, bridge->draw_context.edge, &edge);
mono_field_set_value (context, bridge->draw_context.step, &step);
mono_field_set_value (context, bridge->draw_context.x1, &x1);
mono_field_set_value (context, bridge->draw_context.x2, &x2);
mono_field_set_value (context, bridge->draw_context.y1, &y1);
mono_field_set_value (context, bridge->draw_context.y2, &y2);
mono_field_set_value (context, bridge->draw_context.fill, &fill);
mono_field_set_value (context, bridge->draw_context.arrow_type, &arrow_type);
return mono_object_unbox (context);
}
#include "maigre-style-overrides.c"
typedef void (* DrawFnptr) ();
@ -70,7 +138,7 @@ maigre_style_class_init (MaigreStyleClass *klass)
mono_class_get_method_from_name (
bridge->theme_class,
maigre_style_method_map[i].name,
maigre_style_method_map[i].arg_count);
1);
if (method != NULL) {
DrawFnptr *slot = G_STRUCT_MEMBER_P (
GTK_STYLE_CLASS (klass),