Icon class for interaction with icons
Methods
Public Class
Public Instance
Public Instance Aliases
draw | -> | draw_point | |
to_s | -> | to_str |
Aliases |
Public Class methods
Initialize Icon object.
icon = Subtlext::Icon.new("/path/to/icon") => #<Subtlext::Icon:xxx> icon = Subtlext::Icon.new(8, 8) => #<Subtlext::Icon:xxx>
VALUE subextIconInit(int argc, VALUE *argv, VALUE self) { SubtlextIcon *i = NULL; Data_Get_Struct(self, SubtlextIcon, i); if(i) { VALUE data[3] = { Qnil }; rb_scan_args(argc, argv, "12", &data[0], &data[1], &data[2]); subextSubtlextConnect(NULL); ///< Implicit open connection /* Find or create icon */ if(T_STRING == rb_type(data[0])) ///< Icon path { int hotx = 0, hoty = 0; char buf[100] = { 0 }; #ifdef HAVE_WORDEXP_H /* Expand tildes in path */ wordexp_t we; if(0 == wordexp(RSTRING_PTR(data[0]), &we, 0)) { snprintf(buf, sizeof(buf), "%s", we.we_wordv[0]); wordfree(&we); } else #endif /* HAVE_WORDEXP_H */ snprintf(buf, sizeof(buf), "%s", RSTRING_PTR(data[0])); /* Find file */ if(-1 == access(buf, R_OK)) { char *home = NULL; /* Combine paths */ if((home = getenv("XDG_DATA_HOME"))) { snprintf(buf, sizeof(buf), "%s/subtle/icons/%s", home, RSTRING_PTR(data[0])); } else { snprintf(buf, sizeof(buf), "%s/.local/share/subtle/icons/%s", getenv("HOME"), RSTRING_PTR(data[0])); } /* Check if icon exists */ if(-1 == access(buf, R_OK)) rb_raise(rb_eStandardError, "Invalid icon `%s'", RSTRING_PTR(data[0])); } /* Reading bitmap or pixmap icon file */ if(BitmapSuccess != XReadBitmapFile(display, DefaultRootWindow(display), buf, &i->width, &i->height, &i->pixmap, &hotx, &hoty)) { #ifdef HAVE_X11_XPM_H XpmAttributes attrs; /* We could define a color to use on transparent areas, but * this can be done on init only, so we just ignore it and * expect pixmaps to have no transparent areas at all */ /* Init attributes */ attrs.colormap = DefaultColormap(display, DefaultScreen(display)); attrs.depth = DefaultDepth(display, DefaultScreen(display)); attrs.visual = DefaultVisual(display, DefaultScreen(display)); attrs.valuemask = XpmColormap|XpmDepth|XpmVisual; if(XpmSuccess == XpmReadFileToPixmap(display, DefaultRootWindow(display), buf, &i->pixmap, NULL, &attrs)) { i->flags |= ICON_PIXMAP; i->width = attrs.width; i->height = attrs.height; } else #endif /* HAVE_X11_XPM_H */ { rb_raise(rb_eStandardError, "Invalid icon data"); return Qnil; } } else i->flags |= ICON_BITMAP; } else if(FIXNUM_P(data[0]) && FIXNUM_P(data[1])) ///< Icon dimensions { int depth = 1; /* Create pixmap or bitmap */ if(Qtrue == data[2]) { i->flags |= ICON_PIXMAP; depth = XDefaultDepth(display, DefaultScreen(display)); } else i->flags |= ICON_BITMAP; /* Create empty pixmap */ i->width = FIX2INT(data[0]); i->height = FIX2INT(data[1]); i->pixmap = XCreatePixmap(display, DefaultRootWindow(display), i->width, i->height, depth); } else if(FIXNUM_P(data[0])) { XRectangle geom = { 0 }; i->flags |= (ICON_BITMAP|ICON_FOREIGN); i->pixmap = NUM2LONG(data[0]); subSharedPropertyGeometry(display, i->pixmap, &geom); i->width = geom.width; i->height = geom.height; } else rb_raise(rb_eArgError, "Unexpected value-types"); /* Update object */ rb_iv_set(i->instance, "@width", INT2FIX(i->width)); rb_iv_set(i->instance, "@height", INT2FIX(i->height)); rb_iv_set(i->instance, "@pixmap", LONG2NUM(i->pixmap)); XSync(display, False); ///< Sync all changes } return Qnil; }
Public Instance methods
Convert this Icon to string and concat it multiple times.
icon * 2 => "<>!4<><>!4<>"
VALUE subextIconOperatorMult(VALUE self, VALUE value) { VALUE ret = Qnil; /* Check id and name */ if(FIXNUM_P(value)) { /* Passthru to string class */ ret = rb_funcall(subextIconToString(self), rb_intern("*"), 1, value); } else rb_raise(rb_eArgError, "Unexpected value-type `%s'", rb_obj_classname(value)); return ret; }
Convert this Icon to string and concat given string.
icon + "subtle" => "<>!4<>subtle"
VALUE subextIconOperatorPlus(VALUE self, VALUE value) { return subextSubtlextConcat(subextIconToString(self), value); }
Whether both objects have the same value. Returns -1, 0 or 1 when self is less than, equal to or grater than other. (based on pixmap)
object1 <=> object2 => 0
static VALUE SubtlextEqualSpacePixmap(VALUE self, VALUE other) { return SubtlextSpaceship(self, other, "@pixmap"); }
Whether both objects have the same values (based on geometry).
object1 == object2 => true
VALUE subextIconEqual(VALUE self, VALUE other) { return IconEqual(self, other); }
Whether icon is a bitmap.
icon.bitmap? => true icon.bitmap? => false
VALUE subextIconAskBitmap(VALUE self) { VALUE ret = Qfalse; SubtlextIcon *i = NULL; Data_Get_Struct(self, SubtlextIcon, i); if(i) ret = (i->flags & ICON_BITMAP) ? Qtrue : Qfalse; return ret; }
Clear the icon and optionally set a fore-/background color.
icon.clear => #<Subtlext::Icon:xxx> icon.clear("#ff0000", "#000000") => #<Subtlext::Icon:xxx>
VALUE subextIconClear(int argc, VALUE *argv, VALUE self) { SubtlextIcon *i = NULL; Data_Get_Struct(self, SubtlextIcon, i); if(i) { XGCValues gvals; if(0 == i->gc) ///< Create on demand i->gc = XCreateGC(display, i->pixmap, 0, NULL); /* Update GC */ gvals.foreground = 0; gvals.background = 1; if(i->flags & ICON_PIXMAP) { VALUE colors[2] = { Qnil }; rb_scan_args(argc, argv, "02", &colors[0], &colors[1]); if(!NIL_P(colors[0])) gvals.foreground = subextColorPixel(colors[0], Qnil, Qnil, NULL); if(!NIL_P(colors[1])) gvals.background = subextColorPixel(colors[1], Qnil, Qnil, NULL); } XChangeGC(display, i->gc, GCForeground|GCBackground, &gvals); XFillRectangle(display, i->pixmap, i->gc, 0, 0, i->width, i->height); XFlush(display); } return self; }
Copy area of given width/height from one Icon to another.
icon.copy_area(icon, 0, 0, 10, 10, 0, 0) => #<Subtlext::Icon:xxx>
VALUE subextIconCopyArea(int argc, VALUE *argv, VALUE self) { VALUE data[7] = { Qnil }; rb_scan_args(argc, argv, "16", &data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6]); /* Check object type */ if(rb_obj_is_instance_of(data[0], rb_const_get(mod, rb_intern("Icon")))) { SubtlextIcon *src = NULL, *dest = NULL; Data_Get_Struct(data[0], SubtlextIcon, src); Data_Get_Struct(self, SubtlextIcon, dest); if(src && dest) { int src_x = 0, src_y = 0, dest_x = 0, dest_y = 0; int iwidth = 0, iheight = 0, area_w = 0, area_h = 0; VALUE width = Qnil, height = Qnil; /* Get icon dimesions */ GET_ATTR(self, "@width", width); GET_ATTR(self, "@height", height); iwidth = FIX2INT(width); iheight = FIX2INT(height); /* Check args */ if(!NIL_P(data[1])) src_x = FIX2INT(data[1]); if(!NIL_P(data[2])) src_y = FIX2INT(data[2]); if(!NIL_P(data[3])) area_w = FIX2INT(data[3]); if(!NIL_P(data[4])) area_h = FIX2INT(data[4]); if(!NIL_P(data[5])) dest_x = FIX2INT(data[5]); if(!NIL_P(data[6])) dest_y = FIX2INT(data[6]); /* Sanitize args */ if(0 == area_w) area_w = iwidth; if(0 == area_h) area_h = iheight; if(area_w > dest_x + iwidth) area_w = iwidth - dest_x; if(area_h > dest_y + iheight) area_h = iheight - dest_y; if(0 > src_x || src_x > iwidth) src_x = 0; if(0 > src_y || src_y > iheight) src_y = 0; if(0 > dest_x || dest_x > iwidth) dest_x = 0; if(0 > dest_y || dest_y > iheight) dest_y = 0; /* Create on demand */ if(0 == dest->gc) dest->gc = XCreateGC(display, dest->pixmap, 0, NULL); /* Copy area */ if(src->flags & ICON_PIXMAP && dest->flags & ICON_PIXMAP) { XCopyPlane(display, src->pixmap, dest->pixmap, dest->gc, src_x, src_y, area_w, area_h, dest_x, dest_y, 1); } else XCopyArea(display, src->pixmap, dest->pixmap, dest->gc, src_x, src_y, area_w, area_h, dest_x, dest_y); XFlush(display); } } else rb_raise(rb_eArgError, "Unexpected value-types"); return self; }
Draw a line on the Icon starting at x1/y1 to x2/y2 in given colors.
icon.draw_line(1, 1, 10, 1) => #<Subtlext::Icon:xxx> icon.draw_line(1, 1, 10, 1, "#ff0000", "#000000") => #<Subtlext::Icon:xxx>
VALUE subextIconDrawLine(int argc, VALUE *argv, VALUE self) { VALUE data[6] = { Qnil }; rb_scan_args(argc, argv, "42", &data[0], &data[1], &data[2], &data[3], &data[4], &data[5]); /* Check object types */ if(FIXNUM_P(data[0]) && FIXNUM_P(data[1]) && FIXNUM_P(data[2]) && FIXNUM_P(data[3])) { SubtlextIcon *i = NULL; Data_Get_Struct(self, SubtlextIcon, i); if(i) { XGCValues gvals; /* Create on demand */ if(0 == i->gc) i->gc = XCreateGC(display, i->pixmap, 0, NULL); /* Update GC */ gvals.foreground = 1; gvals.background = 0; if(i->flags & ICON_PIXMAP) { if(!NIL_P(data[4])) gvals.foreground = subextColorPixel(data[4], Qnil, Qnil, NULL); if(!NIL_P(data[5])) gvals.background = subextColorPixel(data[5], Qnil, Qnil, NULL); } XChangeGC(display, i->gc, GCForeground|GCBackground, &gvals); XDrawLine(display, i->pixmap, i->gc, FIX2INT(data[0]), FIX2INT(data[1]), FIX2INT(data[2]), FIX2INT(data[3])); XFlush(display); } } else rb_raise(rb_eArgError, "Unexpected value-types"); return self; }
Draw a pixel on the icon at given coordinates in given colors.
icon.draw_point(1, 1) => #<Subtlext::Icon:xxx> icon.draw_point(1, 1, "#ff0000", "#000000") => #<Subtlext::Icon:xxx>
VALUE subextIconDrawPoint(int argc, VALUE *argv, VALUE self) { VALUE data[4] = { Qnil }; rb_scan_args(argc, argv, "22", &data[0], &data[1], &data[2], &data[3]); /* Check object types */ if(FIXNUM_P(data[0]) && FIXNUM_P(data[1])) { SubtlextIcon *i = NULL; Data_Get_Struct(self, SubtlextIcon, i); if(i) { XGCValues gvals; /* Create on demand */ if(0 == i->gc) i->gc = XCreateGC(display, i->pixmap, 0, NULL); /* Update GC */ gvals.foreground = 1; gvals.background = 0; if(i->flags & ICON_PIXMAP) { if(!NIL_P(data[2])) gvals.foreground = subextColorPixel(data[2], Qnil, Qnil, NULL); if(!NIL_P(data[3])) gvals.background = subextColorPixel(data[3], Qnil, Qnil, NULL); } XChangeGC(display, i->gc, GCForeground|GCBackground, &gvals); XDrawPoint(display, i->pixmap, i->gc, FIX2INT(data[0]), FIX2INT(data[1])); XFlush(display); } } else rb_raise(rb_eArgError, "Unexpected value-types"); return self; }
Draw a rect on the Icon starting at x/y with given width, height and colors.
icon.draw_rect(1, 1, 10, 10, false) => #<Subtlext::Icon:xxx> icon.draw_rect(1, 1, 10, 10, false, "#ff0000", "#000000") => #<Subtlext::Icon:xxx>
VALUE subextIconDrawRect(int argc, VALUE *argv, VALUE self) { VALUE data[7] = { Qnil }; rb_scan_args(argc, argv, "43", &data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6]); /* Check object types */ if(FIXNUM_P(data[0]) && FIXNUM_P(data[1]) && FIXNUM_P(data[2]) && FIXNUM_P(data[3])) { SubtlextIcon *i = NULL; Data_Get_Struct(self, SubtlextIcon, i); if(i) { XGCValues gvals; /* Create on demand */ if(0 == i->gc) i->gc = XCreateGC(display, i->pixmap, 0, NULL); /* Update GC */ gvals.foreground = 1; gvals.background = 0; if(i->flags & ICON_PIXMAP) { if(!NIL_P(data[5])) gvals.foreground = subextColorPixel(data[5], Qnil, Qnil, NULL); if(!NIL_P(data[6])) gvals.background = subextColorPixel(data[6], Qnil, Qnil, NULL); } XChangeGC(display, i->gc, GCForeground|GCBackground, &gvals); /* Draw rect */ if(Qtrue == data[4]) { XFillRectangle(display, i->pixmap, i->gc, FIX2INT(data[0]), FIX2INT(data[1]), FIX2INT(data[2]), FIX2INT(data[3])); } else XDrawRectangle(display, i->pixmap, i->gc, FIX2INT(data[0]), FIX2INT(data[1]), FIX2INT(data[2]), FIX2INT(data[3])); XFlush(display); } } else rb_raise(rb_eArgError, "Unexpected value-types"); return self; }
Whether both objects have the same values and types (based on geometry).
object1.eql? object2 => true
VALUE subextIconEqualTyped(VALUE self, VALUE other) { return IconEqual(self, other); }
Convert this object to hash.
puts object.hash => 1746246187916025425
static VALUE SubtlextHash(VALUE self) { VALUE str = Qnil, id = rb_intern("to_str"); /* Convert to string */ if(rb_respond_to(self, id)) str = rb_funcall(self, id, 0, Qnil); return T_STRING == rb_type(str) ? INT2FIX(rb_str_hash(str)) : Qnil; }
Convert this Icon object to string.
puts icon => "<>!4<>"
VALUE subextIconToString(VALUE self) { VALUE ret = Qnil; SubtlextIcon *i = NULL; Data_Get_Struct(self, SubtlextIcon, i); if(i) { char buf[20] = { 0 }; snprintf(buf, sizeof(buf), "%s%c%ld%s", SEPARATOR, i->flags & ICON_PIXMAP ? '&' : '!', i->pixmap, SEPARATOR); ret = rb_str_new2(buf); } return ret; }