Logging In and Out of Adium, iChat and Skype using AppleScript

Even though I'd rather not, I use not one, not two but three instant messaging applications on my main machine: Adium, iChat and Skype. While Adium allows to connect to almost all IM networks in a slick little interface that feels right at home on Mac OS X, iChat has some unique features going for it, for instance Bonjour as well as audio and video chat, and Skype of course is the only app that can run Skype. Besides, everyone at work uses Skype, so I just have to have it running at all time. Using all three together it not a big problem to me, at and even less of a problem since I wrote two little pieces of AppleScript that allow me to connect and disconnect from all the applications using a command-line scripts. Here are the scripts, both wrapped in an executable (chmod +x) script called either online or offline using the osascript command.

Going offline:

on IsSkypeRunning()
  tell application "System Events" to (name of processes) contains "Skype"
end IsSkypeRunning

on IsAdiumRunning()
  tell application "System Events" to (name of processes) contains "Adium"
end IsAdiumRunning

if IsSkypeRunning() then
  tell application "Skype"
    send command "SET USERSTATUS OFFLINE" script name "Make Skype go offline"
  end tell
end if

tell application "iChat"
  log out
end tell

if IsAdiumRunning() then
  tell application "Adium" to disconnect every account
end if

Going online:

on IsSkypeRunning()
  tell application "System Events" to (name of processes) contains "Skype"
end IsSkypeRunning

on IsAdiumRunning()
  tell application "System Events" to (name of processes) contains "Adium"
end IsAdiumRunning

if IsSkypeRunning() then
  tell application "Skype"
    send command "SET USERSTATUS ONLINE" script name "Make Skype go online"
  end tell
end if

tell application "iChat"
  log in
end tell

if IsAdiumRunning() then
  tell application "Adium" to connect every account
end if

Labels: , , , ,

Getting an SVG Element's Full Bounding Box

Getting the fully-transformed bounding box of a given SVG element is something quite handy and not given for free by the SVG DOM right now. However, the SVG DOM provides all the required foundations to compute such a bounding box, by providing the SVGLocatable::getBBox(), SVGLocatable::getScreenCTM() and SVGPoint::matrixTransform() methods mostly. So, with no further ado, here's the code to a utility getScreenBBox(element) function:

function getScreenBBox (element) {

  // macro to create an SVGPoint object
  function createPoint (x, y) {
    var point = document.documentElement.createSVGPoint();
    point.x = x;
    point.y = y;
    return point;
  }

  // macro to create an SVGRect object
  function createRect (x, y, width, height) {
    var rect = document.documentElement.createSVGRect();
    rect.x = x;
    rect.y = y;
    rect.width = width;
    rect.height = height;
    return rect;
  }

  // get the complete transformation matrix
  var matrix = element.getScreenCTM();
  // get the bounding box of the target element
  var box = element.getBBox();

  // create an array of SVGPoints for each corner
  // of the bounding box and update their location
  // with the transform matrix
  var corners = [];
  var point = createPoint(box.x, box.y);
  corners.push( point.matrixTransform(matrix) );
  point.x = box.x + box.width;
  point.y = box.y;
  corners.push( point.matrixTransform(matrix) );
  point.x = box.x + box.width;
  point.y = box.y + box.height;
  corners.push( point.matrixTransform(matrix) );
  point.x = box.x;
  point.y = box.y + box.height;
  corners.push( point.matrixTransform(matrix) );
  var max = createPoint(corners[0].x, corners[0].y);
  var min = createPoint(corners[0].x, corners[0].y);

  // identify the new corner coordinates of the
  // fully transformed bounding box
  for (var i = 1; i < corners.length; i++) {
    var x = corners[i].x;
    var y = corners[i].y;
    if (x < min.x) {
      min.x = x;
    }
    else if (x > max.x) {
      max.x = x;
    }
    if (y < min.y) {
      min.y = y;
    }
    else if (y > max.y) {
      max.y = y;
    }
  }
  
  // return the bounding box as an SVGRect object
  return createRect(min.x, min.y, max.x - min.x, max.y - min.y);
}

Labels: , ,