class Subtle::Sublet

  1. src/subtle/ruby.c
Superclass: Object

Sublet class for interaction with sublets

Public Instance methods

config -> Hash

Get config hash from config

s.config
=> { :interval => 30 }
[show source]
static VALUE
RubySubletConfig(VALUE self)
{
  SubPanel *p = NULL;
  VALUE hash = Qnil;

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      /* Get config hash */
      if(NIL_P(hash = rb_hash_lookup(config_sublets, CHAR2SYM(p->sublet->name))))
        hash = rb_hash_new();
    }

  return hash;
}
configure -> nil

Configure block for Sublet

configure :sublet do |s|
  s.interval = 60
end
[show source]
static VALUE
RubySubletConfigure(VALUE self,
  VALUE name)
{
  rb_need_block();

  /* Check value type */
  if(T_SYMBOL == rb_type(name))
    {
      SubPanel *p = NULL;

      Data_Get_Struct(self, SubPanel, p);
      if(p)
        {
          VALUE proc = Qnil;

          /* Assume latest sublet */
          proc            = rb_block_proc();
          p->sublet->name = strdup(SYM2CHAR(name));

          /* Define configure method */
          rb_funcall(rb_singleton_class(p->sublet->instance),
            rb_intern("define_method"),
            2, CHAR2SYM("__configure"), proc);
        }
    }
  else rb_raise(rb_eArgError, "Unknown value type for configure");

  return Qnil;
}
data -> String or nil

Get data of Sublet

puts sublet.data
=> "subtle"
[show source]
static VALUE
RubySubletDataReader(VALUE self)
{
  int i;
  VALUE string = Qnil;
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      if(0 < p->sublet->text->nitems)
        {
          /* Concat string */
          for(i = 0; i < p->sublet->text->nitems; i++)
            {
              SubTextItem *item = (SubTextItem *)p->sublet->text->items[i];

              if(Qnil == string) rb_str_new2(item->data.string);
              else rb_str_cat(string, item->data.string, strlen(item->data.string));
            }
        }
    }

  return string;
}
data=(string) -> nil

Set data of Sublet

sublet.data = "subtle"
=> nil
[show source]
static VALUE
RubySubletDataWriter(VALUE self,
  VALUE value)
{
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      /* Check value type */
      if(T_STRING == rb_type(value))
        {
          SubStyle *s = &subtle->styles.sublets, *style = NULL;

          /* Select style */
          if(s->styles && (style = subArrayGet(s->styles, p->sublet->styleid)))
              s = style;

          p->sublet->width = subTextParse(p->sublet->text,
            subtle->styles.sublets.font, RSTRING_PTR(value)) +
            STYLE_WIDTH((*s));
        }
      else rb_raise(rb_eArgError, "Unknown value type");
    }

  return Qnil;
}
geometry -> Subtlext::Geometry

Get geometry of a sublet

sublet.geometry
=> #<Subtlext::Geometry:xxx>
[show source]
VALUE
RubySubletGeometryReader(VALUE self)
{
  SubPanel *p = NULL;
  VALUE geometry = Qnil;

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      SubStyle *s = NULL;
      XRectangle geom = { 0 };
      VALUE subtlext = Qnil, klass = Qnil;

      /* Pick sublet style */
      if(subtle->styles.sublets.styles)
        s = subArrayGet(subtle->styles.sublets.styles, p->sublet->styleid);

      subPanelGeometry(p, s ? s : &subtle->styles.sublets, &geom);

      /* Create geometry object */
      subtlext = rb_const_get(rb_mKernel, rb_intern("Subtlext"));
      klass    = rb_const_get(subtlext, rb_intern("Geometry"));
      geometry = rb_funcall(klass, rb_intern("new"), 4,
        INT2FIX(geom.x), INT2FIX(geom.y), INT2FIX(geom.width),
        INT2FIX(geom.height));
    }

  return geometry;
}
grab(chain, &block) -> nil

Add grabs to sublets

grab "A-b" do |s|
  puts s.name
end
[show source]
static VALUE
RubySubletGrab(VALUE self,
  VALUE name)
{
  /* Check value type */
  if(T_SYMBOL == rb_type(name) && rb_block_given_p())
    {
      SubPanel *p = NULL;

      Data_Get_Struct(self, SubPanel, p);
      if(p)
        {
          int i;
          char buf[64] = { 0 };
          VALUE meth = Qnil;

          /* Add proc as instance method */
          snprintf(buf, sizeof(buf), "__grab_%s", SYM2CHAR(name));

          rb_funcall(rb_singleton_class(p->sublet->instance),
            rb_intern("define_method"), 2, CHAR2SYM(buf), rb_block_proc());

          meth = rb_obj_method(p->sublet->instance, CHAR2SYM(buf));

          /* Find grabs with this symbol */
          for(i = 0; i < subtle->grabs->ndata; i++)
            {
              SubGrab *g = GRAB(subtle->grabs->data[i]);

              if(g->flags & SUB_RUBY_DATA && g->data.num == name)
                {
                  g->flags    ^= (SUB_RUBY_DATA|SUB_GRAB_PROC);
                  g->data.num  = (unsigned long)meth;

                  rb_ary_push(shelter, meth); ///< Protect from GC
                }
            }
        }
    }
  else rb_raise(rb_eArgError, "Unknown value type for grab");

  return Qnil;
}
helper -> nil

Helper block for Sublet

helper do |s|
  def test
    puts "test"
  end
end
[show source]
static VALUE
RubySubletHelper(VALUE self)
{
  SubPanel *p = NULL;

  rb_need_block();

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      /* Instance eval the block */
      rb_yield_values(1, p->sublet->instance);
      rb_obj_instance_eval(0, 0, p->sublet->instance);
    }

  return Qnil;
}
hide -> nil

Hide sublet from panel

sublet.hide
=> nil
[show source]
static VALUE
RubySubletHide(VALUE self,
  VALUE value)
{
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      p->flags |= SUB_PANEL_HIDDEN;

      /* Update screens */
      subScreenUpdate();
      subScreenRender();
    }

  return Qnil;
}
interval -> Fixnum

Get interval time of Sublet

puts sublet.interval
=> 60
[show source]
static VALUE
RubySubletIntervalReader(VALUE self)
{
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);

  return p ? INT2FIX(p->sublet->interval) : Qnil;
}
interval=(fixnum) -> nil

Set interval time of Sublet

sublet.interval = 60
=> nil
[show source]
static VALUE
RubySubletIntervalWriter(VALUE self,
  VALUE value)
{
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      if(FIXNUM_P(value))
        {
          p->sublet->interval = FIX2INT(value);
          p->sublet->time     = subSubtleTime() + p->sublet->interval;

          if(0 < p->sublet->interval)
            p->sublet->flags |= SUB_SUBLET_INTERVAL;
          else p->sublet->flags &= ~SUB_SUBLET_INTERVAL;
        }
      else rb_raise(rb_eArgError, "Unknown value type `%s'", rb_obj_classname(value));
    }

  return Qnil;
}
name -> String

Get name of Sublet

puts sublet.name
=> "sublet"
[show source]
static VALUE
RubySubletNameReader(VALUE self)
{
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);

  return p ? rb_str_new2(p->sublet->name) : Qnil;
}
on(event, &block) -> nil

Event block for hooks

on :event do |s|
  puts s.name
end
[show source]
static VALUE
RubySubletOn(VALUE self,
  VALUE event)
{
  /* Check value type */
  if(T_SYMBOL == rb_type(event) && rb_block_given_p())
    {
      SubPanel *p = NULL;

      Data_Get_Struct(self, SubPanel, p);
      if(p)
        {
          char buf[64] = { 0 };
          int i, arity = 0;
          VALUE proc = Qnil, sing = Qnil, meth = Qnil;

          RubyMethods methods[] =
          {
            { CHAR2SYM("run"),        CHAR2SYM("__run"),    SUB_SUBLET_RUN,    1 },
            { CHAR2SYM("data"),       CHAR2SYM("__data"),   SUB_SUBLET_DATA,   2 },
            { CHAR2SYM("watch"),      CHAR2SYM("__watch"),  SUB_SUBLET_WATCH,  1 },
            { CHAR2SYM("unload"),     CHAR2SYM("__unload"), SUB_SUBLET_UNLOAD, 1 },
            { CHAR2SYM("mouse_down"), CHAR2SYM("__down"),   SUB_PANEL_DOWN,    4 },
            { CHAR2SYM("mouse_over"), CHAR2SYM("__over"),   SUB_PANEL_OVER,    1 },
            { CHAR2SYM("mouse_out"),  CHAR2SYM("__out"),    SUB_PANEL_OUT,     1 }
          };

          /* Collect stuff */
          proc  = rb_block_proc();
          arity = rb_proc_arity(proc);
          sing  = rb_singleton_class(p->sublet->instance);
          meth  = rb_intern("define_method");

          /* Special hooks */
          for(i = 0; LENGTH(methods) > i; i++)
            {
              if(methods[i].sym == event)
                {
                  /* Check proc arity */
                  if(-1 == arity || (1 <= arity && methods[i].arity >= arity))
                    {
                      /* Add flags */
                      if(methods[i].flags & (SUB_PANEL_DOWN|
                          SUB_PANEL_OVER|SUB_PANEL_OUT))
                        p->flags |= methods[i].flags;
                      else p->sublet->flags |= methods[i].flags;

                      /* Create instance method from proc */
                      rb_funcall(sing, meth, 2, methods[i].real, proc);

                      return Qnil;
                    }
                  else rb_raise(rb_eArgError, "Wrong number of arguments (%d for %d)",
                    arity, methods[i].arity);
               }
            }

          /* Generic hooks */
          snprintf(buf, sizeof(buf), "__hook_%s", SYM2CHAR(event));
          rb_funcall(sing, meth, 2, CHAR2SYM(buf), proc);

          RubyEvalHook(event, rb_obj_method(p->sublet->instance,
            CHAR2SYM(buf)));
        }
    }
  else rb_raise(rb_eArgError, "Unknown value type for on");

  return Qnil;
}
render -> nil

Render a Sublet

sublet.render
=> nil
[show source]
static VALUE
RubySubletRender(VALUE self)
{
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);
  if(p) subScreenRender();

  return Qnil;
}
screen -> Subtlext::Screen

Get screen of a sublet

sublet.screen
=> #<Subtlext::screen:xxx>
[show source]
VALUE
RubySubletScreenReader(VALUE self)
{
  SubPanel *p = NULL;
  VALUE screen = Qnil;

  Data_Get_Struct(self, SubPanel, p);
  if(p) screen = RubySubtleToSubtlext(p->screen);

  return screen;
}
show -> nil

Show sublet on panel

sublet.show
=> nil
[show source]
static VALUE
RubySubletShow(VALUE self)
{
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      p->flags &= ~SUB_PANEL_HIDDEN;

      /* Update screens */
      subScreenUpdate();
      subScreenRender();
    }

  return Qnil;
}
style=(string) -> nil
style=(symbol) -> nil

Set style of Sublet

sublet.style = :subtle
=> nil
[show source]
static VALUE
RubySubletStyleWriter(VALUE self,
  VALUE value)
{
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      /* Check value type */
      if(FIXNUM_P(value))
        {
          SubStyle *s = &subtle->styles.sublets, *style = NULL;

          /* Select style */
          if(s->styles && (style = subArrayGet(s->styles, FIX2INT(value))))
            {
              s                  = style;
              p->sublet->styleid = FIX2INT(value);
            }

          p->sublet->width = subTextParse(p->sublet->text,
            subtle->styles.sublets.font, RSTRING_PTR(value)) +
            STYLE_WIDTH((*s));
        }
      else rb_raise(rb_eArgError, "Unknown value type");
    }

  return Qnil;
}
unwatch -> true or false

Remove watch from Sublet

unwatch
=> true
[show source]
static VALUE
RubySubletUnwatch(VALUE self)
{
  VALUE ret = Qfalse;
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      /* Probably a socket */
      if(p->sublet->flags & SUB_SUBLET_SOCKET)
        {
          XDeleteContext(subtle->dpy, subtle->windows.support, p->sublet->watch);
          subEventWatchDel(p->sublet->watch);

          p->sublet->flags &= ~SUB_SUBLET_SOCKET;
          p->sublet->watch  = 0;

          ret = Qtrue;
        }
#ifdef HAVE_SYS_INOTIFY_H
      /* Inotify file */
      else if(p->sublet->flags & SUB_SUBLET_INOTIFY)
        {
          subSubtleLogDebug("Inotify: remove watch=%d\n", p->sublet->watch);

          XDeleteContext(subtle->dpy, subtle->windows.support, p->sublet->watch);
          inotify_rm_watch(subtle->notify, p->sublet->watch);

          p->sublet->flags &= ~SUB_SUBLET_INOTIFY;
          p->sublet->watch  = 0;

          ret = Qtrue;
        }
#endif /* HAVE_SYS_INOTIFY_H */
    }

  return ret;
}
warn(string) -> nil

Print sublet warning

sublet.warn("test")
=> "<WARNING SUBLET sublet> test"
[show source]
static VALUE
RubySubletWarn(VALUE self,
  VALUE str)
{
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);
  if(p && T_STRING == rb_type(str))
    subSubtleLogSubletError(p->sublet->name, RSTRING_PTR(str));

  return Qnil;
}
watch(source) -> true or false

Add watch file via inotify or socket

watch "/path/to/file"
=> true
@socket = TCPSocket("localhost", 6600)
watch @socket
[show source]
static VALUE
RubySubletWatch(VALUE self,
  VALUE value)
{
  VALUE ret = Qfalse;
  SubPanel *p = NULL;

  Data_Get_Struct(self, SubPanel, p);
  if(p)
    {
      if(!(p->sublet->flags & (SUB_SUBLET_SOCKET|SUB_SUBLET_INOTIFY)) &&
          RTEST(value))
        {
          /* Socket file descriptor or ruby socket */
          if(FIXNUM_P(value) || rb_respond_to(value, rb_intern("fileno")))
            {
              int flags = 0;

              p->sublet->flags |= SUB_SUBLET_SOCKET;

              /* Get socket file descriptor */
              if(FIXNUM_P(value)) p->sublet->watch = FIX2INT(value);
              else
                {
                  p->sublet->watch = FIX2INT(rb_funcall(value, rb_intern("fileno"),
                    0, NULL));
                }

              XSaveContext(subtle->dpy, subtle->windows.support,
                p->sublet->watch, (void *)p);
              subEventWatchAdd(p->sublet->watch);

              /* Set nonblocking */
              if(-1 == (flags = fcntl(p->sublet->watch, F_GETFL, 0))) flags = 0;
              fcntl(p->sublet->watch, F_SETFL, flags | O_NONBLOCK);

              ret = Qtrue;
            }
#ifdef HAVE_SYS_INOTIFY_H
          else if(T_STRING == rb_type(value)) /// Inotify file
            {
              char buf[100] = { 0 };

#ifdef HAVE_WORDEXP_H
              /* Expand tildes in path */
              wordexp_t we;

              if(0 == wordexp(RSTRING_PTR(value), &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(value));

              /* Create inotify watch */
              if(0 < (p->sublet->watch = inotify_add_watch(
                  subtle->notify, buf, IN_MODIFY)))
                {
                  p->sublet->flags |= SUB_SUBLET_INOTIFY;

                  XSaveContext(subtle->dpy, subtle->windows.support,
                    p->sublet->watch, (void *)p);
                  subSubtleLogDebug("Inotify: add watch=%s\n", buf);

                  ret = Qtrue;
                }
              else subSubtleLogWarn("Cannot watch file `%s': %s\n",
                buf, strerror(errno));
            }
#endif /* HAVE_SYS_INOTIFY_H */
          else rb_raise(rb_eArgError, "Unexpected value-type `%s'",
            rb_obj_classname(value));
        }
    }

  return ret;
}