[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: gEDA-user: DRC UI mockup
On Sun, 2009-03-29 at 16:21 +0100, Peter Clifton wrote:
> NB: Unfortunately, I don't have a lot of time to develop these ideas in
> terms of code at the moment, so don't expect to see this on my branch
> any time soon!
Ok, so I wanted this to fix some DRC problems on a board I was working
with. Since coding tools is _always_ more fun than doing work, I hacked
some proof of concept code until it worked for what I needed. (A list of
violations, and a way to jump to them in arbitrary order).
Screenshot here:
http://www2.eng.cam.ac.uk/~pcjc2/geda/drc_for_real.png
Compare to:
http://www2.eng.cam.ac.uk/~pcjc2/geda/drc_mockup.png
Patch in progress attached.
--
Peter Clifton
Electrical Engineering Division,
Engineering Department,
University of Cambridge,
9, JJ Thomson Avenue,
Cambridge
CB3 0FA
Tel: +44 (0)7729 980173 - (No signal in the lab!)
diff --git a/src/Makefile.am b/src/Makefile.am
index 146fbb9..f35a45f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -241,6 +241,8 @@ LIBGTK_SRCS = \
hid/gtk/gui-dialog-print.c \
hid/gtk/gui-dialog-size.c \
hid/gtk/gui-dialog.c \
+ hid/gtk/gui-drc-window.c \
+ hid/gtk/gui-drc-window.h \
hid/gtk/gui-keyref-window.c \
hid/gtk/gui-library-window.c \
hid/gtk/gui-library-window.h \
diff --git a/src/action.c b/src/action.c
index 7b78fed..6e7af6f 100644
--- a/src/action.c
+++ b/src/action.c
@@ -1746,6 +1746,8 @@ ActionDRCheck (int argc, char **argv, int x, int y)
{
int count;
+ /* TODO: Override some of these messages for a GUI driven DRC ? */
+
Message (_("Rules are minspace %d.%02d, minoverlap %d.%d "
"minwidth %d.%02d, minsilk %d.%02d\n"
"min drill %d.%02d, min annular ring %d.%02d\n"),
diff --git a/src/find.c b/src/find.c
index 94ace4d..9c584a6 100644
--- a/src/find.c
+++ b/src/find.c
@@ -157,11 +157,62 @@ RCSID ("$Id$");
#define IS_PV_ON_PAD(PV,Pad) \
( IsPointInPad((PV)->X, (PV)->Y, MAX((PV)->Thickness/2 +Bloat,0), (Pad)))
-static char drc_dialog_message[289];
+#define LENGTH_TO_HUMAN(value) (Settings.grid_units_mm ? ((value) / 100000.0 * 25.4) : ((value) / 100.0))
+#define LENGTH_DIGITS (Settings.grid_units_mm ? 4 : 2)
+#define LENGTH_UNITS_STRING (Settings.grid_units_mm ? "mm" : "mils")
+
+
+static DRC_VIOLATION
+*pcb_drc_violation_new (char *title,
+ char *explanation,
+ int x, int y,
+ int angle,
+ double measured_value,
+ double required_value,
+ int value_digits,
+ const char *value_units,
+ int object_count,
+ long int *object_id_list,
+ int *object_type_list)
+{
+ DRC_VIOLATION *violation = malloc (sizeof (DRC_VIOLATION));
+
+ violation->title = strdup (title);
+ violation->explanation = strdup (explanation);
+ violation->x = x;
+ violation->y = y;
+ violation->angle = angle;
+ violation->measured_value = measured_value;
+ violation->required_value = required_value;
+ violation->value_digits = value_digits;
+ violation->value_units = value_units;
+ violation->object_count = object_count;
+ violation->object_id_list = object_id_list;
+ violation->object_type_list = object_type_list;
+
+ return violation;
+}
+
+static void
+pcb_drc_violation_free (DRC_VIOLATION *violation)
+{
+ free (violation->title);
+ free (violation->explanation);
+ free (violation);
+}
+
+static char drc_dialog_message[289] = {0,};
static void
reset_drc_dialog_message(void)
{
- drc_dialog_message[0] = 0;
+ if (gui->drc_gui != NULL)
+ {
+ gui->drc_gui->reset_drc_dialog_message ();
+ }
+ else
+ {
+ drc_dialog_message[0] = 0;
+ }
}
#ifdef __GNUC__
static void append_drc_dialog_message(const char *fmt, ...)
@@ -170,18 +221,42 @@ static void append_drc_dialog_message(const char *fmt, ...)
static void
append_drc_dialog_message(const char *fmt, ...)
{
- size_t len = strlen (drc_dialog_message),
- remained = sizeof (drc_dialog_message) - len - 1;
+ size_t len, remained;
va_list ap;
+
va_start (ap, fmt);
+
+ if (gui->drc_gui != NULL)
+ {
+ printf ("FUBAR\n");
+ //gui->drc_gui->append_drc_dialog_messagev (fmt, ap);
+ }
+ else
+ {
+ len = strlen (drc_dialog_message);
+ remained = sizeof (drc_dialog_message) - len - 1;
#ifdef HAVE_VSNPRINTF
- vsnprintf (drc_dialog_message + len, remained, fmt, ap);
+ vsnprintf (drc_dialog_message + len, remained, fmt, ap);
#else
- vsprintf (drc_dialog_message + len, fmt, ap);
+ vsprintf (drc_dialog_message + len, fmt, ap);
#endif
+ }
+
va_end (ap);
}
+static void
+append_drc_violation (DRC_VIOLATION *violation)
+{
+ if (gui->drc_gui != NULL)
+ {
+ gui->drc_gui->append_drc_violation (violation);
+ }
+ else
+ {
+ /* FALLBACK TO THE OLD WAY? */
+ }
+}
/*
* message when asked about continuing DRC checks after next
* violation is found.
@@ -194,9 +269,18 @@ static int
throw_drc_dialog(void)
{
int r;
- append_drc_dialog_message (DRC_CONTINUE);
- r = gui->confirm_dialog (drc_dialog_message, DRC_CANCEL, DRC_NEXT);
- reset_drc_dialog_message();
+
+ if (gui->drc_gui != NULL)
+ {
+ r = gui->drc_gui->throw_drc_dialog ();
+// gui->drc_gui->reset_drc_dialog_message ();
+ }
+ else
+ {
+ append_drc_dialog_message (DRC_CONTINUE);
+ r = gui->confirm_dialog (drc_dialog_message, DRC_CANCEL, DRC_NEXT);
+ reset_drc_dialog_message();
+ }
return r;
}
@@ -261,6 +345,8 @@ static Boolean PrintAndSelectUnusedPinsAndPadsOfElement (ElementTypePtr,
static void DrawNewConnections (void);
static void ResetConnections (Boolean);
static void DumpList (void);
+static void LocateError (LocationType *, LocationType *);
+static void BuildObjectList (int *, long int **, int **);
static void GotoError (void);
static Boolean DRCFind (int, void *, void *, void *);
static Boolean ListStart (int, void *, void *, void *);
@@ -3467,7 +3553,13 @@ DumpList (void)
static Boolean
DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
{
- reset_drc_dialog_message();
+ LocationType x, y;
+ int object_count;
+ long int *object_id_list;
+ int *object_type_list;
+ DRC_VIOLATION *violation;
+
+// reset_drc_dialog_message();
if (PCB->Shrink != 0)
{
Bloat = -PCB->Shrink;
@@ -3488,7 +3580,6 @@ DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
Message
(_
("WARNING!! Design Rule Error - potential for broken trace!\n"));
- append_drc_dialog_message(_("potential for broken trace\n"));
/* make the flag changes undoable */
TheFlag = FOUNDFLAG | SELECTEDFLAG;
ResetConnections (False);
@@ -3511,7 +3602,25 @@ DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
User = False;
drc = False;
drcerr_count++;
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Potential for broken trace"),
+ _("Insufficient overlap between objects can lead to broken tracks\n"
+ "due to registration errors with old wheel style photo-plotters."),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ 0, /* MAGNITURE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN(PCB->Shrink),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
+
if (!throw_drc_dialog())
return (True);
IncrementUndoSerialNumber ();
@@ -3531,7 +3640,6 @@ DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
{
DumpList ();
Message (_("WARNING! Design Rule error - copper areas too close!\n"));
- append_drc_dialog_message(_("copper areas too close\n"));
/* make the flag changes undoable */
TheFlag = FOUNDFLAG | SELECTEDFLAG;
ResetConnections (False);
@@ -3552,7 +3660,24 @@ DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
DoIt (True, True);
DumpList ();
drcerr_count++;
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Copper areas too close"),
+ _("Circuits that are too close may bridge during imaging, etching,\n"
+ "plating, or soldering processes resulting in a direct short."),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ 0, /* MAGNITURE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN(PCB->Bloat),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
User = False;
drc = False;
if (!throw_drc_dialog())
@@ -3603,6 +3728,13 @@ static int
drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
int type, void *ptr1, void *ptr2)
{
+ char *message;
+ LocationType x, y;
+ int object_count;
+ long int *object_id_list;
+ int *object_type_list;
+ DRC_VIOLATION *violation;
+
LineTypePtr line = (LineTypePtr) ptr2;
ArcTypePtr arc = (ArcTypePtr) ptr2;
PinTypePtr pin = (PinTypePtr) ptr2;
@@ -3619,9 +3751,8 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
{
AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
SET_FLAG (TheFlag, line);
- Message (_("Line with insufficient clearance inside polygon\n"));
- append_drc_dialog_message(_("line inside polygon\n"
- "with insufficient clearance\n"));
+ message = _("Line with insufficient clearance inside polygon\n");
+ Message (message);
goto doIsBad;
}
break;
@@ -3630,9 +3761,8 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
{
AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
SET_FLAG (TheFlag, arc);
- Message (_("Arc with insufficient clearance inside polygon\n"));
- append_drc_dialog_message(_("arc inside polygon\n"
- "with insufficient clearance\n"));
+ message = _("Arc with insufficient clearance inside polygon\n");
+ Message (message);
goto doIsBad;
}
break;
@@ -3642,9 +3772,8 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
{
AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
SET_FLAG (TheFlag, pad);
- Message (_("Pad with insufficient clearance inside polygon\n"));
- append_drc_dialog_message(_("pad inside polygon\n"
- "with insufficient clearance\n"));
+ message = _("Pad with insufficient clearance inside polygon\n");
+ Message (message);
goto doIsBad;
}
break;
@@ -3653,9 +3782,8 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
{
AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
SET_FLAG (TheFlag, pin);
- Message (_("Pin with insufficient clearance inside polygon\n"));
- append_drc_dialog_message(_("pin inside polygon\n"
- "with insufficient clearance\n"));
+ message = _("Pin with insufficient clearance inside polygon\n");
+ Message (message);
goto doIsBad;
}
break;
@@ -3664,16 +3792,15 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
{
AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
SET_FLAG (TheFlag, pin);
- Message (_("Via with insufficient clearance inside polygon\n"));
- append_drc_dialog_message(_("via inside polygon\n"
- "with insufficient clearance\n"));
+ message = _("Via with insufficient clearance inside polygon\n");
+ Message (message);
goto doIsBad;
}
break;
default:
Message ("hace: Bad Plow object in callback\n");
- append_drc_dialog_message(_("wrong object inside polygon\n"
- "with insufficient clearance\n"));
+// append_drc_dialog_message(_("wrong object inside polygon\n"
+// "with insufficient clearance\n"));
}
return 0;
@@ -3683,7 +3810,24 @@ doIsBad:
DrawPolygon (layer, polygon, 0);
DrawObject (type, ptr1, ptr2, 0);
drcerr_count++;
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (message,
+ _("Circuits that are too close may bridge during imaging, etching,\n"
+ "plating, or soldering processes resulting in a direct short."),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ 0, /* MAGNITURE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN(PCB->Bloat),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
if (!throw_drc_dialog())
{
IsBad = True;
@@ -3701,9 +3845,16 @@ doIsBad:
int
DRCAll (void)
{
+ LocationType x, y;
+ int object_count;
+ long int *object_id_list;
+ int *object_type_list;
+ DRC_VIOLATION *violation;
int tmpcnt;
int nopastecnt = 0;
+ reset_drc_dialog_message();
+
IsBad = False;
drcerr_count = 0;
SaveStackAndVisibility ();
@@ -3779,11 +3930,27 @@ DRCAll (void)
AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
SET_FLAG (TheFlag, line);
Message (_("Line is too thin\n"));
- append_drc_dialog_message(_("too thin line\n"));
DrawLine (layer, line, 0);
drcerr_count++;
SetThing (LINE_TYPE, layer, line, line);
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Line width is too thin"),
+ _("Process specifications dictate a minimum feature-width\n"
+ "that can reliably be reproduced"),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN(line->Thickness),
+ LENGTH_TO_HUMAN(PCB->minWid),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
if (!throw_drc_dialog())
{
IsBad = True;
@@ -3807,11 +3974,27 @@ DRCAll (void)
AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
SET_FLAG (TheFlag, arc);
Message (_("Arc is too thin\n"));
- append_drc_dialog_message(_("too thin arc\n"));
DrawArc (layer, arc, 0);
drcerr_count++;
SetThing (ARC_TYPE, layer, arc, arc);
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Arc width is too thin"),
+ _("Process specifications dictate a minimum feature-width\n"
+ "that can reliably be reproduced"),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN(arc->Thickness),
+ LENGTH_TO_HUMAN(PCB->minWid),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
if (!throw_drc_dialog())
{
IsBad = True;
@@ -3837,11 +4020,27 @@ DRCAll (void)
SET_FLAG (TheFlag, pin);
Message (_
("Pin annular ring is too small based on minimum annular ring\n"));
- append_drc_dialog_message(_("pin ring thinner\nthan min annular ring\n"));
DrawPin (pin, 0);
drcerr_count++;
SetThing (PIN_TYPE, element, pin, pin);
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Pin annular ring too small"),
+ _("Annular rings that are too small may erode during etching,\n"
+ "resulting in a broken connection"),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN((pin->Thickness - pin->DrillingHole) / 2),
+ LENGTH_TO_HUMAN(PCB->minRing),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
if (!throw_drc_dialog())
{
IsBad = True;
@@ -3855,11 +4054,26 @@ DRCAll (void)
AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
SET_FLAG (TheFlag, pin);
Message (_("Pin drill size is too small\n"));
- append_drc_dialog_message(_("too small pin drill\n"));
DrawPin (pin, 0);
drcerr_count++;
SetThing (PIN_TYPE, element, pin, pin);
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Pin drill size is too small"),
+ _("Process rules dictate the minimum drill size which can be used"),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN(pin->DrillingHole),
+ LENGTH_TO_HUMAN(PCB->minDrill),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
if (!throw_drc_dialog())
{
IsBad = True;
@@ -3883,11 +4097,27 @@ DRCAll (void)
AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
SET_FLAG (TheFlag, pad);
Message (_("Pad is too thin\n"));
- append_drc_dialog_message(_("too thin pad\n"));
DrawPad (pad, 0);
drcerr_count++;
SetThing (PAD_TYPE, element, pad, pad);
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Pad is too thin"),
+ _("Pads which are too thin may erode during etching,\n"
+ "resulting in a broken or unreliable connection"),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN(pad->Thickness),
+ LENGTH_TO_HUMAN(PCB->minWid),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
if (!throw_drc_dialog())
{
IsBad = True;
@@ -3913,11 +4143,27 @@ DRCAll (void)
SET_FLAG (TheFlag, via);
Message (_
("Via annular ring is too small based on minimum annular ring\n"));
- append_drc_dialog_message(_("via ring thinner\nthan min annular ring\n"));
DrawVia (via, 0);
drcerr_count++;
SetThing (VIA_TYPE, via, via, via);
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Via annular ring too small"),
+ _("Annular rings that are too small may erode during etching,\n"
+ "resulting in a broken connection"),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN((via->Thickness - via->DrillingHole) / 2),
+ LENGTH_TO_HUMAN(PCB->minRing),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
if (!throw_drc_dialog())
{
IsBad = True;
@@ -3931,11 +4177,26 @@ DRCAll (void)
AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
SET_FLAG (TheFlag, via);
Message (_("Via drill size is too small\n"));
- append_drc_dialog_message(_("too small via drill\n"));
DrawVia (via, 0);
drcerr_count++;
SetThing (VIA_TYPE, via, via, via);
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Via drill size is too small"),
+ _("Process rules dictate the minimum drill size which can be used"),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN(via->DrillingHole),
+ LENGTH_TO_HUMAN(PCB->minDrill),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
if (!throw_drc_dialog())
{
IsBad = True;
@@ -3964,11 +4225,27 @@ DRCAll (void)
{
SET_FLAG (TheFlag, line);
Message (_("Silk line is too thin\n"));
- append_drc_dialog_message(_("too thin silk line\n"));
DrawLine (layer, line, 0);
drcerr_count++;
SetThing (LINE_TYPE, layer, line, line);
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Silk line is too thin"),
+ _("Process specifications dictate a minimum silkscreen feature-width\n"
+ "that can reliably be reproduced"),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ LENGTH_TO_HUMAN(line->Thickness),
+ LENGTH_TO_HUMAN(PCB->minSlk),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
if (!throw_drc_dialog())
{
IsBad = True;
@@ -3998,13 +4275,30 @@ DRCAll (void)
SET_FLAG (TheFlag, element);
Message (_("Element %s has %d silk lines which are too thin\n"),
UNKNOWN (NAMEONPCB_NAME (element)), tmpcnt);
- append_drc_dialog_message (_
- ("%i silk lines\n of element %s\nare too thin\n"),
- tmpcnt, UNKNOWN (NAMEONPCB_NAME (element)));
+// append_drc_dialog_message (_
+// ("%i silk lines\n of element %s\nare too thin\n"),
+// tmpcnt, UNKNOWN (NAMEONPCB_NAME (element)));
DrawElement (element, 0);
drcerr_count++;
SetThing (ELEMENT_TYPE, element, element, element);
- GotoError ();
+ LocateError (&x, &y);
+ BuildObjectList (&object_count, &object_id_list, &object_type_list);
+ violation = pcb_drc_violation_new (_("Element {FIXME} has {FIXME} silk lines which are too thin"),
+ _("Process specifications dictate a minimum silkscreen feature-width\n"
+ "that can reliably be reproduced"),
+ x, y,
+ 0, /* ANGLE OF ERROR UNKNOWN */
+ 0, /* MINIMUM OFFENDING WIDTH UNKNOWN */
+ LENGTH_TO_HUMAN(PCB->minSlk),
+ LENGTH_DIGITS,
+ LENGTH_UNITS_STRING,
+ object_count,
+ object_id_list,
+ object_type_list);
+ append_drc_violation (violation);
+ pcb_drc_violation_free (violation);
+ free (object_id_list);
+ free (object_type_list);
if (!throw_drc_dialog())
{
IsBad = True;
@@ -4036,36 +4330,34 @@ DRCAll (void)
}
/*----------------------------------------------------------------------------
- * center the display to show the offending item (thing)
+ * Locate the coordinatates of offending item (thing)
*/
static void
-GotoError (void)
+LocateError (LocationType *x, LocationType *y)
{
- LocationType X, Y;
-
switch (thing_type)
{
case LINE_TYPE:
{
LineTypePtr line = (LineTypePtr) thing_ptr3;
- X = (line->Point1.X + line->Point2.X) / 2;
- Y = (line->Point1.Y + line->Point2.Y) / 2;
+ *x = (line->Point1.X + line->Point2.X) / 2;
+ *y = (line->Point1.Y + line->Point2.Y) / 2;
break;
}
case ARC_TYPE:
{
ArcTypePtr arc = (ArcTypePtr) thing_ptr3;
- X = arc->X;
- Y = arc->Y;
+ *x = arc->X;
+ *y = arc->Y;
break;
}
case POLYGON_TYPE:
{
PolygonTypePtr polygon = (PolygonTypePtr) thing_ptr3;
- X =
+ *x =
(polygon->Clipped->contours->xmin +
polygon->Clipped->contours->xmax) / 2;
- Y =
+ *y =
(polygon->Clipped->contours->ymin +
polygon->Clipped->contours->ymax) / 2;
break;
@@ -4074,33 +4366,75 @@ GotoError (void)
case VIA_TYPE:
{
PinTypePtr pin = (PinTypePtr) thing_ptr3;
- X = pin->X;
- Y = pin->Y;
+ *x = pin->X;
+ *y = pin->Y;
break;
}
case PAD_TYPE:
{
PadTypePtr pad = (PadTypePtr) thing_ptr3;
- X = (pad->Point1.X + pad->Point2.X) / 2;
- Y = (pad->Point1.Y + pad->Point2.Y) / 2;
+ *x = (pad->Point1.X + pad->Point2.X) / 2;
+ *y = (pad->Point1.Y + pad->Point2.Y) / 2;
break;
}
case ELEMENT_TYPE:
{
ElementTypePtr element = (ElementTypePtr) thing_ptr3;
- X = element->MarkX;
- Y = element->MarkY;
+ *x = element->MarkX;
+ *y = element->MarkY;
break;
}
default:
return;
}
+}
+
+
+/*----------------------------------------------------------------------------
+ * Build a list of the of offending items by ID. (Currently just "thing")
+ */
+static void
+BuildObjectList (int *object_count, long int **object_id_list, int **object_type_list)
+{
+ *object_count = 0;
+ *object_id_list = NULL;
+
+ switch (thing_type)
+ {
+ case LINE_TYPE:
+ case ARC_TYPE:
+ case POLYGON_TYPE:
+ case PIN_TYPE:
+ case VIA_TYPE:
+ case PAD_TYPE:
+ case ELEMENT_TYPE:
+ *object_count = 1;
+ *object_id_list = malloc (sizeof (long int));
+ *object_type_list = malloc (sizeof (int));
+ **object_id_list = ((AnyObjectType *)thing_ptr3)->ID;
+ **object_type_list = thing_type;
+ return;
+
+ default:
+ return;
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ * center the display to show the offending item (thing)
+ */
+static void
+GotoError (void)
+{
+ LocationType X, Y;
+
+ LocateError (&X, &Y);
+
{
- int digits = Settings.grid_units_mm ? 4: 2;
double scale = Settings.grid_units_mm ? COOR_TO_MM : 1./100,
x = X * scale, y = Y * scale;
- Message (_("near location (%.*f,%.*f)\n"), digits, x, digits, y);
- append_drc_dialog_message("near (%.*f,%.*f)\n", digits, x, digits, y);
+ Message (_("near location (%.*f,%.*f)\n"), LENGTH_DIGITS, x, LENGTH_DIGITS, y);
}
switch (thing_type)
{
diff --git a/src/gpcb-menu.res b/src/gpcb-menu.res
index 5e56536..26e15e8 100644
--- a/src/gpcb-menu.res
+++ b/src/gpcb-menu.res
@@ -445,6 +445,7 @@ MainMenu =
{Window
{"Library" DoWindows(Library) a={"i" "<Key>i"}}
{"Message Log" DoWindows(Log)}
+ {"DRC Check" DoWindows(DRC)}
{"Netlist" DoWindows(Netlist)}
{"Command Entry" Command() a={":" "<Key>:"}}
{"Pinout" Display(Pinout) a={"Shift-D" "Shift<Key>d"}}
diff --git a/src/hid.h b/src/hid.h
index 6cceaaf..a8b256a 100644
--- a/src/hid.h
+++ b/src/hid.h
@@ -229,6 +229,31 @@ typedef enum
PCB_WATCH_HANGUP = 1 << 3 /**< As in POLLHUP */
} PCBWatchFlags;
+typedef struct
+{
+ char *title;
+ char *explanation;
+ int x;
+ int y;
+ int angle;
+ double measured_value;
+ double required_value;
+ int value_digits;
+ const char *value_units;
+ int object_count;
+ long int *object_id_list;
+ int *object_type_list;
+} DRC_VIOLATION;
+
+/* DRC GUI Hooks */
+ typedef struct
+ {
+ void (*reset_drc_dialog_message) (void);
+ void (*append_drc_violation) (DRC_VIOLATION *violation);
+// void (*append_drc_dialog_messagev) (const char *fmt, va_list va);
+ int (*throw_drc_dialog) (void);
+ } HID_DRC_GUI;
+
/* This is the main HID structure. */
typedef struct
@@ -536,6 +561,8 @@ typedef enum
Returns nonzero if the user wishes to cancel the operation. */
int (*progress) (int so_far_, int total_, const char *message_);
+ HID_DRC_GUI *drc_gui;
+
} HID;
/* Call this as soon as possible from main(). No other HID calls are
diff --git a/src/hid/batch/batch.c b/src/hid/batch/batch.c
index 3e80139..5479b46 100644
--- a/src/hid/batch/batch.c
+++ b/src/hid/batch/batch.c
@@ -507,7 +507,8 @@ HID batch_gui = {
batch_attribute_dialog,
batch_show_item,
batch_beep,
- batch_progress
+ batch_progress,
+ 0 /* batch_drc_gui */
};
#include "dolists.h"
diff --git a/src/hid/bom/bom.c b/src/hid/bom/bom.c
index 18fca46..9892269 100644
--- a/src/hid/bom/bom.c
+++ b/src/hid/bom/bom.c
@@ -587,6 +587,7 @@ HID bom_hid = {
0, /* bom_show_item */
0, /* bom_beep */
0, /* bom_progress */
+ 0, /* bom_drc_gui */
};
void
diff --git a/src/hid/common/hidnogui.c b/src/hid/common/hidnogui.c
index 57509dc..5c33332 100644
--- a/src/hid/common/hidnogui.c
+++ b/src/hid/common/hidnogui.c
@@ -394,7 +394,8 @@ HID hid_nogui = {
nogui_attribute_dialog,
nogui_show_item,
nogui_beep,
- nogui_progress
+ nogui_progress,
+ 0 /* nogui_drc_gui */
};
#define AD(x) if (!d->x) d->x = s->x
@@ -447,4 +448,5 @@ apply_default_hid (HID * d, HID * s)
AD (show_item);
AD (beep);
AD (progress);
+ AD (drc_gui);
}
diff --git a/src/hid/gerber/gerber.c b/src/hid/gerber/gerber.c
index 0f70e2a..29f69bf 100644
--- a/src/hid/gerber/gerber.c
+++ b/src/hid/gerber/gerber.c
@@ -1129,7 +1129,9 @@ static HID gerber_hid = {
0 /* gerber_fileselect */ ,
0 /* gerber_attribute_dialog */ ,
0 /* gerber_show_item */ ,
- 0 /* gerber_beep */
+ 0 /* gerber_beep */ ,
+ 0 /* gerber_progress */ ,
+ 0 /* gerber_drc_gui */
};
void
diff --git a/src/hid/gtk/gtkhid-main.c b/src/hid/gtk/gtkhid-main.c
index ad11ba8..4653335 100644
--- a/src/hid/gtk/gtkhid-main.c
+++ b/src/hid/gtk/gtkhid-main.c
@@ -1474,6 +1474,12 @@ ghid_progress (int so_far, int total, const char *message)
}
/* ---------------------------------------------------------------------- */
+HID_DRC_GUI ghid_drc_gui = {
+ ghid_drc_window_reset_message,
+ ghid_drc_window_append_violation,
+// ghid_drc_window_append_messagev,
+ ghid_drc_window_throw_dialog
+};
HID ghid_hid = {
sizeof (HID),
@@ -1534,7 +1540,8 @@ HID ghid_hid = {
ghid_attribute_dialog,
ghid_show_item,
ghid_beep,
- ghid_progress
+ ghid_progress,
+ &ghid_drc_gui
};
HID ghid_extents = {
@@ -1595,7 +1602,8 @@ HID ghid_extents = {
0 /* ghid_attribute_dialog */ ,
0 /* ghid_show_item */ ,
0 /* ghid_beep */ ,
- 0 /* ghid_progress */
+ 0 /* ghid_progress */ ,
+ 0 /* ghid_drc_gui */
};
/* ------------------------------------------------------------
@@ -2340,8 +2348,8 @@ CursorAction(int argc, char **argv, int x, int y)
/* ------------------------------------------------------------ */
static const char dowindows_syntax[] =
-"DoWindows(1|2|3|4)\n"
-"DoWindows(Layout|Library|Log|Netlist|Preferences)";
+"DoWindows(1|2|3|4|5|6)\n"
+"DoWindows(Layout|Library|Log|Netlist|Preferences|DRC)";
static const char dowindows_help[] =
"Open various GUI windows.";
@@ -2371,6 +2379,10 @@ Open the netlist window.
@itemx Preferences
Open the preferences window.
+@item 6
+@itemx DRC
+Open the DRC violations window.
+
@end table
%end-doc */
@@ -2399,6 +2411,10 @@ DoWindows (int argc, char **argv, int x, int y)
{
ghid_config_window_show ();
}
+ else if (strcmp (a, "6") == 0 || strcasecmp (a, "DRC") == 0)
+ {
+ ghid_drc_window_show (TRUE);
+ }
else
{
AFAIL (dowindows);
diff --git a/src/hid/gtk/gui-config.c b/src/hid/gtk/gui-config.c
index 1b50d32..23c3164 100644
--- a/src/hid/gtk/gui-config.c
+++ b/src/hid/gtk/gui-config.c
@@ -130,6 +130,8 @@ static ConfigAttribute config_attributes[] = {
{"top-window-height", CONFIG_Integer, &_ghidgui.top_window_height},
{"log-window-width", CONFIG_Integer, &_ghidgui.log_window_width},
{"log-window-height", CONFIG_Integer, &_ghidgui.log_window_height},
+ {"drc-window-width", CONFIG_Integer, &_ghidgui.drc_window_width},
+ {"drc-window-height", CONFIG_Integer, &_ghidgui.drc_window_height},
{"library-window-width", CONFIG_Integer, &_ghidgui.library_window_width},
{"library-window-height", CONFIG_Integer, &_ghidgui.library_window_height},
{"netlist-window-height", CONFIG_Integer, &_ghidgui.netlist_window_height},
diff --git a/src/hid/gtk/gui-drc-window.c b/src/hid/gtk/gui-drc-window.c
new file mode 100644
index 0000000..7632994
--- /dev/null
+++ b/src/hid/gtk/gui-drc-window.c
@@ -0,0 +1,732 @@
+/* $Id$ */
+
+/*
+ * COPYRIGHT
+ *
+ * PCB, interactive printed circuit board design
+ * Copyright (C) 1994,1995,1996 Thomas Nau
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Contact addresses for paper mail and Email:
+ * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
+ * Thomas.Nau@xxxxxxxxxxxxx
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "error.h"
+#include "search.h"
+#include "draw.h"
+#include "undo.h"
+#include "gui.h"
+#include "gui-drc-window.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+RCSID ("$Id$");
+
+static GtkWidget *drc_window, *drc_list;
+static GtkListStore *drc_list_model = NULL;
+static int num_violations = 0;
+
+/* Remember user window resizes. */
+static gint
+drc_window_configure_event_cb (GtkWidget * widget,
+ GdkEventConfigure * ev, gpointer data)
+{
+ ghidgui->drc_window_width = widget->allocation.width;
+ ghidgui->drc_window_height = widget->allocation.height;
+ ghidgui->config_modified = TRUE;
+
+ return FALSE;
+}
+
+static void
+drc_close_cb (gpointer data)
+{
+ gtk_widget_destroy (drc_window);
+ drc_window = NULL;
+}
+
+static void
+drc_destroy_cb (GtkWidget * widget, gpointer data)
+{
+ drc_window = NULL;
+}
+
+enum {
+ DRC_VIOLATION_NUM_COL = 0,
+ DRC_TITLE_COL,
+ DRC_EXPLANATION_COL,
+ DRC_X_COORD_COL,
+ DRC_Y_COORD_COL,
+ DRC_ANGLE_COL,
+ DRC_MEASURED_VALUE_COL,
+ DRC_REQUIRED_VALUE_COL,
+ DRC_VALUE_DIGITS_COL,
+ DRC_VALUE_UNITS_COL,
+ DRC_OBJECT_COUNT_COL,
+ DRC_OBJECT_ID_LIST_COL,
+ DRC_OBJECT_TYPE_LIST_COL,
+ NUM_DRC_COLUMNS
+};
+
+
+#warning NASTY, DOESNT USE UNDO PROPERLY
+static void
+unset_found_flags (int AndDraw)
+{
+ int flag = FOUNDFLAG;
+ int change = 0;
+
+ VIA_LOOP (PCB->Data);
+ {
+ if (TEST_FLAG (flag, via))
+ {
+ if (AndDraw)
+ AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
+ CLEAR_FLAG (flag, via);
+ if (AndDraw)
+ DrawVia (via, 0);
+ change = True;
+ }
+ }
+ END_LOOP;
+ ELEMENT_LOOP (PCB->Data);
+ {
+ PIN_LOOP (element);
+ {
+ if (TEST_FLAG (flag, pin))
+ {
+ if (AndDraw)
+ AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
+ CLEAR_FLAG (flag, pin);
+ if (AndDraw)
+ DrawPin (pin, 0);
+ change = True;
+ }
+ }
+ END_LOOP;
+ PAD_LOOP (element);
+ {
+ if (TEST_FLAG (flag, pad))
+ {
+ if (AndDraw)
+ AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
+ CLEAR_FLAG (flag, pad);
+ if (AndDraw)
+ DrawPad (pad, 0);
+ change = True;
+ }
+ }
+ END_LOOP;
+ }
+ END_LOOP;
+ RAT_LOOP (PCB->Data);
+ {
+ if (TEST_FLAG (flag, line))
+ {
+ if (AndDraw)
+ AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
+ CLEAR_FLAG (flag, line);
+ if (AndDraw)
+ DrawRat (line, 0);
+ change = True;
+ }
+ }
+ END_LOOP;
+ COPPERLINE_LOOP (PCB->Data);
+ {
+ if (TEST_FLAG (flag, line))
+ {
+ if (AndDraw)
+ AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
+ CLEAR_FLAG (flag, line);
+ if (AndDraw)
+ DrawLine (layer, line, 0);
+ change = True;
+ }
+ }
+ ENDALL_LOOP;
+ COPPERARC_LOOP (PCB->Data);
+ {
+ if (TEST_FLAG (flag, arc))
+ {
+ if (AndDraw)
+ AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
+ CLEAR_FLAG (flag, arc);
+ if (AndDraw)
+ DrawArc (layer, arc, 0);
+ change = True;
+ }
+ }
+ ENDALL_LOOP;
+ COPPERPOLYGON_LOOP (PCB->Data);
+ {
+ if (TEST_FLAG (flag, polygon))
+ {
+ if (AndDraw)
+ AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
+ CLEAR_FLAG (flag, polygon);
+ if (AndDraw)
+ DrawPolygon (layer, polygon, 0);
+ change = True;
+ }
+ }
+ ENDALL_LOOP;
+ if (change)
+ {
+ SetChangedFlag (True);
+ if (AndDraw)
+ {
+ IncrementUndoSerialNumber ();
+ Draw ();
+ }
+ }
+}
+
+static void
+selection_changed_cb (GtkTreeSelection *selection, gpointer user_data)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ int object_count;
+#if 0
+ long int *object_id_list;
+ int *object_type_list;
+#else
+ long int object_id;
+ int object_type;
+#endif
+ int i;
+ int x_coord, y_coord;
+
+#warning CHEATING HERE!
+ /* I happen to know I'm only putting 0 or 1 items in the lists of objects.
+ To do this properly requires some memory allocation and tracking to
+ avoid leaks! */
+
+ /* Check there is anything selected, if not; return */
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ /* Unflag objects */
+ unset_found_flags (True);
+ return;
+ }
+
+ /* Check the selected node has children, if so; return. */
+ if (gtk_tree_model_iter_has_child (model, &iter))
+ return;
+
+ gtk_tree_model_get (model, &iter,
+ DRC_X_COORD_COL, &x_coord,
+ DRC_Y_COORD_COL, &y_coord,
+ DRC_OBJECT_COUNT_COL, &object_count,
+#if 0
+ DRC_OBJECT_ID_LIST_COL, &object_id_list,
+ DRC_OBJECT_TYPE_LIST_COL, &object_type_list,
+#else
+ DRC_OBJECT_ID_LIST_COL, &object_id,
+ DRC_OBJECT_TYPE_LIST_COL, &object_type,
+#endif
+ -1);
+
+ unset_found_flags (False);
+
+ /* Flag the objects listed against this DRC violation */
+ for (i = 0; i < object_count; i++)
+ {
+ int found_type;
+ void *ptr1, *ptr2, *ptr3;
+
+ found_type = SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3,
+ object_id, object_type);
+ if (found_type == NO_TYPE)
+ {
+ Message (_("Object ID %i identified during DRC was not found. Stale DRC window?\n"),
+ object_id);
+ continue;
+ }
+ SET_FLAG (FOUNDFLAG, (AnyObjectType *)ptr2);
+ switch (object_type)
+ {
+ case LINE_TYPE:
+ case ARC_TYPE:
+ case POLYGON_TYPE:
+ ChangeGroupVisibility (GetLayerNumber (PCB->Data, (LayerTypePtr) ptr1), True, True);
+ }
+ DrawObject (object_type, ptr1, ptr2, 0);
+ }
+ Draw();
+ CenterDisplay (x_coord, y_coord, False);
+}
+
+
+enum
+{
+ PROP_TITLE = 1,
+ PROP_EXPLANATION,
+ PROP_X_COORD,
+ PROP_Y_COORD,
+ PROP_ANGLE,
+ PROP_MEASURED_VALUE,
+ PROP_REQUIRED_VALUE,
+ PROP_VALUE_DIGITS,
+ PROP_VALUE_UNITS
+};
+
+
+static GObjectClass *ghid_violation_renderer_parent_class = NULL;
+
+
+/*! \brief GObject finalise handler
+ *
+ * \par Function Description
+ * Just before the GhidViolationRenderer GObject is finalized, free our
+ * allocated data, and then chain up to the parent's finalize handler.
+ *
+ * \param [in] widget The GObject being finalized.
+ */
+static void
+ghid_violation_renderer_finalize (GObject * object)
+{
+ GhidViolationRenderer *renderer = GHID_VIOLATION_RENDERER (object);
+
+ g_free (renderer->title);
+ g_free (renderer->explanation);
+ g_free (renderer->value_units);
+
+ G_OBJECT_CLASS (ghid_violation_renderer_parent_class)->finalize (object);
+}
+
+
+/*! \brief GObject property setter function
+ *
+ * \par Function Description
+ * Setter function for GhidViolationRenderer's GObject properties,
+ * "settings-name" and "toplevel".
+ *
+ * \param [in] object The GObject whose properties we are setting
+ * \param [in] property_id The numeric id. under which the property was
+ * registered with g_object_class_install_property()
+ * \param [in] value The GValue the property is being set from
+ * \param [in] pspec A GParamSpec describing the property being set
+ */
+static void
+ghid_violation_renderer_set_property (GObject * object, guint property_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GhidViolationRenderer *renderer = GHID_VIOLATION_RENDERER (object);
+ char *markup;
+
+ switch (property_id)
+ {
+ case PROP_TITLE:
+ g_free (renderer->title);
+ renderer->title = g_value_dup_string (value);
+ break;
+ case PROP_EXPLANATION:
+ g_free (renderer->explanation);
+ renderer->explanation = g_value_dup_string (value);
+ break;
+ case PROP_X_COORD:
+ renderer->x_coord = g_value_get_int (value);
+ break;
+ case PROP_Y_COORD:
+ renderer->y_coord = g_value_get_int (value);
+ break;
+ case PROP_ANGLE:
+ renderer->angle = g_value_get_int (value);
+ break;
+ case PROP_MEASURED_VALUE:
+ renderer->measured_value = g_value_get_double (value);
+ break;
+ case PROP_REQUIRED_VALUE:
+ renderer->required_value = g_value_get_double (value);
+ break;
+ case PROP_VALUE_DIGITS:
+ renderer->value_digits = g_value_get_int (value);
+ break;
+ case PROP_VALUE_UNITS:
+ g_free (renderer->value_units);
+ renderer->value_units = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ return;
+ }
+
+ markup = g_strdup_printf ("<b>%s (%.*f %s)</b>\n"
+ "<span font_size='1024'> </span>\n"
+ "<small>"
+ "<i>%s</i>\n"
+ "<span font_size='6144'> </span>\n"
+ "Required: %.*f %s"
+ "</small>",
+ renderer->title,
+ renderer->value_digits,
+ renderer->measured_value,
+ renderer->value_units,
+
+ renderer->explanation,
+
+ renderer->value_digits,
+ renderer->required_value,
+ renderer->value_units);
+
+ g_object_set (object, "markup", markup, NULL);
+ g_free (markup);
+}
+
+
+/*! \brief GObject property getter function
+ *
+ * \par Function Description
+ * Getter function for GhidViolationRenderer's GObject properties,
+ * "settings-name" and "toplevel".
+ *
+ * \param [in] object The GObject whose properties we are getting
+ * \param [in] property_id The numeric id. under which the property was
+ * registered with g_object_class_install_property()
+ * \param [out] value The GValue in which to return the value of the property
+ * \param [in] pspec A GParamSpec describing the property being got
+ */
+static void
+ghid_violation_renderer_get_property (GObject * object, guint property_id,
+ GValue * value, GParamSpec * pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+
+}
+
+
+/*! \brief GType class initialiser for GhidViolationRenderer
+ *
+ * \par Function Description
+ * GType class initialiser for GhidViolationRenderer. We override our parent
+ * virtual class methods as needed and register our GObject properties.
+ *
+ * \param [in] klass The GhidViolationRendererClass we are initialising
+ */
+static void
+ghid_violation_renderer_class_init (GhidViolationRendererClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = ghid_violation_renderer_finalize;
+ gobject_class->set_property = ghid_violation_renderer_set_property;
+ gobject_class->get_property = ghid_violation_renderer_get_property;
+
+ ghid_violation_renderer_parent_class = g_type_class_peek_parent (klass);
+
+ g_object_class_install_property (gobject_class, PROP_TITLE,
+ g_param_spec_string ("title",
+ "",
+ "",
+ "",
+ G_PARAM_WRITABLE));
+ g_object_class_install_property (gobject_class, PROP_EXPLANATION,
+ g_param_spec_string ("explanation",
+ "",
+ "",
+ "",
+ G_PARAM_WRITABLE));
+ g_object_class_install_property (gobject_class, PROP_X_COORD,
+ g_param_spec_int ("x-coord",
+ "",
+ "",
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_WRITABLE));
+ g_object_class_install_property (gobject_class, PROP_Y_COORD,
+ g_param_spec_int ("y-coord",
+ "",
+ "",
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_WRITABLE));
+ g_object_class_install_property (gobject_class, PROP_ANGLE,
+ g_param_spec_int ("angle",
+ "",
+ "",
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_WRITABLE));
+ g_object_class_install_property (gobject_class, PROP_MEASURED_VALUE,
+ g_param_spec_double ("measured-value",
+ "",
+ "",
+ -G_MAXDOUBLE,
+ G_MAXDOUBLE,
+ 0.,
+ G_PARAM_WRITABLE));
+ g_object_class_install_property (gobject_class, PROP_REQUIRED_VALUE,
+ g_param_spec_double ("required-value",
+ "",
+ "",
+ -G_MINDOUBLE,
+ G_MAXDOUBLE,
+ 0.,
+ G_PARAM_WRITABLE));
+ g_object_class_install_property (gobject_class, PROP_VALUE_DIGITS,
+ g_param_spec_int ("value-digits",
+ "",
+ "",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_WRITABLE));
+ g_object_class_install_property (gobject_class, PROP_VALUE_UNITS,
+ g_param_spec_string ("value-units",
+ "",
+ "",
+ "",
+ G_PARAM_WRITABLE));
+}
+
+
+/*! \brief Function to retrieve GhidViolationRenderer's GType identifier.
+ *
+ * \par Function Description
+ * Function to retrieve GhidViolationRenderer's GType identifier.
+ * Upon first call, this registers the GhidViolationRenderer in the GType system.
+ * Subsequently it returns the saved value from its first execution.
+ *
+ * \return the GType identifier associated with GhidViolationRenderer.
+ */
+GType
+ghid_violation_renderer_get_type ()
+{
+ static GType ghid_violation_renderer_type = 0;
+
+ if (!ghid_violation_renderer_type)
+ {
+ static const GTypeInfo ghid_violation_renderer_info = {
+ sizeof (GhidViolationRendererClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) ghid_violation_renderer_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GhidViolationRenderer),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+
+ ghid_violation_renderer_type =
+ g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT, "GhidViolationRenderer",
+ &ghid_violation_renderer_info, 0);
+ }
+
+ return ghid_violation_renderer_type;
+}
+
+
+/*! \brief Convenience function to create a new violation renderer
+ *
+ * \par Function Description
+ * Convenience function which creates a GhidViolationRenderer.
+ *
+ * \return The GhidViolationRenderer created.
+ */
+GtkCellRenderer *
+ghid_violation_renderer_new (void)
+{
+ GhidViolationRenderer *renderer;
+
+ renderer = g_object_new (GHID_TYPE_VIOLATION_RENDERER,
+ "ypad", 6,
+ NULL);
+
+ return GTK_CELL_RENDERER (renderer);
+// return gtk_cell_renderer_text_new ();
+}
+
+
+void
+ghid_drc_window_show (gboolean raise)
+{
+ GtkWidget *vbox, *hbox, *button, *scrolled_window;
+ GtkCellRenderer *violation_renderer;
+
+ if (drc_window)
+ {
+ if (raise)
+ gtk_window_present(GTK_WINDOW(drc_window));
+ return;
+ }
+
+ drc_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_signal_connect (G_OBJECT (drc_window), "destroy",
+ G_CALLBACK (drc_destroy_cb), NULL);
+ g_signal_connect (G_OBJECT (drc_window), "configure_event",
+ G_CALLBACK (drc_window_configure_event_cb), NULL);
+ gtk_window_set_title (GTK_WINDOW (drc_window), _("PCB DRC"));
+ gtk_window_set_wmclass (GTK_WINDOW (drc_window), "PCB_DRC", "PCB");
+ gtk_window_set_default_size (GTK_WINDOW (drc_window),
+ ghidgui->drc_window_width,
+ ghidgui->drc_window_height);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+ gtk_container_add (GTK_CONTAINER (drc_window), vbox);
+
+ drc_list_model = gtk_list_store_new (NUM_DRC_COLUMNS,
+ G_TYPE_INT, /* DRC_VIOLATION_NUM_COL */
+ G_TYPE_STRING, /* DRC_TITLE_COL */
+ G_TYPE_STRING, /* DRC_EXPLANATION_COL */
+ G_TYPE_INT, /* DRC_X_COORD_COL */
+ G_TYPE_INT, /* DRC_Y_COORD_COL */
+ G_TYPE_INT, /* DRC_ANGLE_COL */
+ G_TYPE_DOUBLE, /* DRC_MEASURED_VALUE_COL */
+ G_TYPE_DOUBLE, /* DRC_REQUIRED_VALUE_COL */
+ G_TYPE_INT, /* DRC_VALUE_DIGITS_COL */
+ G_TYPE_STRING, /* DRC_VALUE_UNITS_COL */
+ G_TYPE_INT, /* DRC_OBJECT_COUNT_COL */
+#warning CHEATING HERE!
+ /* I happen to know I'm only putting 0 or 1 items in the lists of objects.
+ To do this properly requires some memory allocation and tracking to
+ avoid leaks! */
+#if 0
+ G_TYPE_POINTER, /* DRC_OBJECT_ID_LIST_COL */
+ G_TYPE_POINTER); /* DRC_OBJECT_TYPE_LIST_COL */
+#else
+ G_TYPE_LONG, /* DRC_OBJECT_ID_LIST_COL */
+ G_TYPE_INT); /* DRC_OBJECT_TYPE_LIST_COL */
+#endif
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), scrolled_window,
+ TRUE /* EXPAND */, TRUE /* FILL */, 0 /* PADDING */);
+
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ drc_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (drc_list_model));
+ gtk_container_add (GTK_CONTAINER (scrolled_window), drc_list);
+
+ gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (drc_list), TRUE);
+ g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (drc_list)), "changed",
+ G_CALLBACK (selection_changed_cb), NULL);
+
+ violation_renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (drc_list),
+ -1, /* APPEND */
+ _("No."), /* TITLE */
+ violation_renderer,
+ "text", DRC_VIOLATION_NUM_COL,
+ NULL);
+
+ violation_renderer = ghid_violation_renderer_new ();
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (drc_list),
+ -1, /* APPEND */
+ _("Violation details"), /* TITLE */
+ violation_renderer,
+ "title", DRC_TITLE_COL,
+ "explanation", DRC_EXPLANATION_COL,
+ "x-coord", DRC_X_COORD_COL,
+ "y-coord", DRC_Y_COORD_COL,
+ "angle", DRC_ANGLE_COL,
+ "measured-value", DRC_MEASURED_VALUE_COL,
+ "required-value", DRC_REQUIRED_VALUE_COL,
+ "value-digits", DRC_VALUE_DIGITS_COL,
+ "value-units", DRC_VALUE_UNITS_COL,
+ NULL);
+
+ hbox = gtk_hbutton_box_new ();
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (drc_close_cb), NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+
+ gtk_widget_realize (drc_window);
+ if (Settings.AutoPlace)
+ gtk_widget_set_uposition (GTK_WIDGET (drc_window), 10, 10);
+ gtk_widget_show_all (drc_window);
+}
+
+#define UNIT1(value) (Settings.grid_units_mm ? ((value) / 100000.0 * 25.4) : ((value) / 100.0))
+#define UNIT(value) UNIT1(value) , (Settings.grid_units_mm ? "mm" : "mils")
+
+void ghid_drc_window_append_violation (DRC_VIOLATION *violation)
+{
+ GtkTreeIter iter;
+ long int ID = 0;
+ int type = NO_TYPE;
+
+ /* Ensure the required structures are setup */
+ ghid_drc_window_show (FALSE);
+
+ num_violations++;
+
+ /* Copy the violating object lists */
+#warning CHEATING HERE!
+ /* I happen to know I'm only putting 0 or 1 items in the lists of objects.
+ To do this properly requires some memory allocation and tracking to
+ avoid leaks! */
+ if (violation->object_count > 0)
+ {
+ ID = violation->object_id_list[0];
+ type = violation->object_type_list[0];
+ }
+
+ gtk_list_store_append (drc_list_model, &iter);
+ gtk_list_store_set (drc_list_model, &iter,
+ DRC_VIOLATION_NUM_COL, num_violations,
+ DRC_TITLE_COL, violation->title,
+ DRC_EXPLANATION_COL, violation->explanation,
+ DRC_X_COORD_COL, violation->x,
+ DRC_Y_COORD_COL, violation->y,
+ DRC_ANGLE_COL, violation->angle,
+ DRC_MEASURED_VALUE_COL, violation->measured_value,
+ DRC_REQUIRED_VALUE_COL, violation->required_value,
+ DRC_VALUE_DIGITS_COL, violation->value_digits,
+ DRC_VALUE_UNITS_COL, violation->value_units,
+ DRC_OBJECT_COUNT_COL, violation->object_count,
+ DRC_OBJECT_ID_LIST_COL, ID, /* violation->object_id_list, */
+ DRC_OBJECT_TYPE_LIST_COL, type, /* violation->object_type_list, */
+ -1);
+}
+
+void ghid_drc_window_reset_message (void)
+{
+ // printf ("RESET DRC WINDOW\n");
+ if (drc_list_model != NULL)
+ gtk_list_store_clear (drc_list_model);
+ num_violations = 0;
+}
+
+int ghid_drc_window_throw_dialog (void)
+{
+ // printf ("THROW DRC WINDOW\n");
+ ghid_drc_window_show (TRUE);
+ return 1;
+}
+
diff --git a/src/hid/gtk/gui.h b/src/hid/gtk/gui.h
index 771056b..f76e3b3 100644
--- a/src/hid/gtk/gui.h
+++ b/src/hid/gtk/gui.h
@@ -189,6 +189,8 @@ typedef struct
top_window_height,
log_window_width,
log_window_height,
+ drc_window_width,
+ drc_window_height,
keyref_window_width,
keyref_window_height,
library_window_width,
@@ -402,6 +404,14 @@ void ghid_dialog_print (HID *);
int ghid_attribute_dialog (HID_Attribute *, int, HID_Attr_Val *, const char *, const char *);
+/* gui-drc-window.c */
+void ghid_drc_window_show (gboolean raise);
+void ghid_drc_window_reset_message (void);
+void ghid_drc_window_append_violation (DRC_VIOLATION *violation);
+//void ghid_drc_window_append_mesage (const char *fmt, ...);
+void ghid_drc_window_append_messagev (const char *fmt, va_list va);
+int ghid_drc_window_throw_dialog (void);
+
/* gui-route-style function prototypes.
*/
/* In gui-dialog-size.c */
diff --git a/src/hid/lesstif/main.c b/src/hid/lesstif/main.c
index d2b680b..99f9851 100644
--- a/src/hid/lesstif/main.c
+++ b/src/hid/lesstif/main.c
@@ -3928,7 +3928,8 @@ HID lesstif_gui = {
lesstif_attribute_dialog,
lesstif_show_item,
lesstif_beep,
- lesstif_progress
+ lesstif_progress,
+ 0 /* lesstif_drc_gui */
};
#include "dolists.h"
diff --git a/src/hid/lpr/lpr.c b/src/hid/lpr/lpr.c
index cbf19c6..31d288e 100644
--- a/src/hid/lpr/lpr.c
+++ b/src/hid/lpr/lpr.c
@@ -163,7 +163,8 @@ HID lpr_hid = {
0 /* lpr_attribute_dialog */ ,
0 /* lpr_show_item */ ,
0 /* lpr_beep */ ,
- 0 /* lpr_progress */
+ 0 /* lpr_progress */ ,
+ 0 /* lpr_drc_gui */
};
void
diff --git a/src/hid/nelma/nelma.c b/src/hid/nelma/nelma.c
index e548bc0..2dfe41a 100644
--- a/src/hid/nelma/nelma.c
+++ b/src/hid/nelma/nelma.c
@@ -1102,7 +1102,8 @@ HID nelma_hid = {
0 /* nelma_attribute_dialog */ ,
0 /* nelma_show_item */ ,
0 /* nelma_beep */ ,
- 0 /* nelma_progress */
+ 0 /* nelma_progress */ ,
+ 0 /* nelma_drc_gui */
};
#include "dolists.h"
diff --git a/src/hid/png/png.c b/src/hid/png/png.c
index ae4c95f..aa9dc52 100644
--- a/src/hid/png/png.c
+++ b/src/hid/png/png.c
@@ -1376,7 +1376,8 @@ HID png_hid = {
0 /* png_attribute_dialog */ ,
0 /* png_show_item */ ,
0 /* png_beep */ ,
- 0 /* png_progress */
+ 0 /* png_progress */ ,
+ 0 /* png_drc_gui */
};
#include "dolists.h"
diff --git a/src/hid/ps/eps.c b/src/hid/ps/eps.c
index be49202..3dc8510 100644
--- a/src/hid/ps/eps.c
+++ b/src/hid/ps/eps.c
@@ -663,7 +663,9 @@ static HID eps_hid = {
0 /* eps_prompt_for */ ,
0 /* eps_attribute_dialog */ ,
0 /* eps_show_item */ ,
- 0 /* eps_beep */
+ 0 /* eps_beep */ ,
+ 0 /* eps_progress */ ,
+ 0 /* eps_drc_gui */
};
void
diff --git a/src/hid/ps/ps.c b/src/hid/ps/ps.c
index cb96675..880b2ee 100644
--- a/src/hid/ps/ps.c
+++ b/src/hid/ps/ps.c
@@ -1203,7 +1203,8 @@ HID ps_hid = {
0 /* ps_attribute_dialog */ ,
0 /* ps_show_item */ ,
0 /* ps_beep */ ,
- 0 /* ps_progress */
+ 0 /* ps_progress */ ,
+ 0 /* ps_drc_gui */
};
#include "dolists.h"
_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user