Sunday, September 05, 2010

Updated Path Tools Eclipse plug-in

What's new?
  • The Custom commands can now we edited using the table editor which allows you to use a display labels and wildcard patterns for the command. The display label is used in the menu items that invoke the commands. The wildcard patterns are used to determine if the command applies to the selected file.

  • The Path Tools commands remain enabled even if there is no file selected in the Eclipse workbench. The commands operate on the workspace folder when no file is selected in the workbench.
Read more about Path Tools here.

Tuesday, May 11, 2010

LinearLayout gravity and layout_gravity explained

Recently I started hacking on Android. Android uses Java as the development language which made it very easy to get started :) .

I am very familiar with Swing and SWT GUI layout mechanism of Layout Managers and Layouts respectively. I was happy to find out that Android also uses a notion of View Groups which are analogous to the Layout Managers. The Android supports several View Groups, LinearLayout, RelativeLayout to name a few. There many more.

The Android View Groups employ a notion of LayoutParams that are analogous to layout constraints used by Swing Layout Managers. The LayoutParams configure the way the Android View Group lays out it's children views. In Android the GUI can be either built programmatically using Java code or using an XML file. The structure of the XML elements parallels the structure of View object you may build programatically. The XML attributes are used to configure the Layout Params.

LinearLayout

The LinearLayout is a commonly used View Group that lays out it's children views either horizontally or vertically. More details of LinearLayout read this.

android:gravity and android:layout_gravity

After reading the documentation I set out to use the Linear Layout and I came across the the following layout params:
  • android:gravity
  • android:layout_gravity
I must say that my initial experience was a little frustrating. Based on the documentation it was not very clear how the above layout parameters work. After a little bit of googling I soon found out that many people have run into this. So I dove in to find out more details and finally understood how to use these layout parameters with Linear Layout. I will explain using an example layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical" android:background="#666666">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Linear Layout - horizontal, gravity=center"
android:textColor="#FFFFFF" android:padding="2dip" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:orientation="horizontal"
android:layout_height="0dip" android:layout_weight="1"
android:gravity="center" android:background="#EEEEEE">

<Button android:id="@+id/Button01" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="top"
android:text="top"></Button>
<Button android:id="@+id/Button02" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center"
android:text="center"></Button>
<Button android:id="@+id/Button03" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="bottom"
android:layout_gravity="bottom"></Button>
</LinearLayout>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Linear Layout - vertical, gravity=center"
android:textColor="#FFFFFF" android:padding="2dip" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:orientation="vertical"
android:layout_height="0dip" android:layout_weight="1"
android:gravity="center" android:background="#DDDDDD">

<Button android:id="@+id/Button04" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="left"
android:text="left"></Button>
<Button android:id="@+id/Button05" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center"
android:text="center"></Button>
<Button android:id="@+id/Button06" android:layout_height="wrap_content"
android:text="right" android:layout_gravity="right"
android:layout_width="wrap_content"></Button>
</LinearLayout>
</LinearLayout>
This results in the following layout:


android:gravity attribute

Strictly speaking android:gravity is not a Layout Param. The android:gravity is really an attribute of the View Group. It controls the way the contents of the View Group will be positioned horizontally and vertically.

In the above example the top Linear Layout is a horizontal Linear Layout. So setting the android:gravity=center has an effect of positioning the set of buttons in the horizontal center.

In the above example the bottom Linear Layout is a vertical Linear Layout. So setting the android:gravity=center has an effect of positioning the set of buttons in the vertical center.

android:layout_gravity Layout Param

The android:layout_gravity is a Layout Param. Not all View Groups support this Layout Param. See the documentation to find out which Layout Params are supported by a particular View Group. Linear Layout does support android:layout_gravity Layout Param.

For a horizontal Linear Layout the following values make sense:
  • top
  • center
  • bottom
That is because the children of a horizontal Linear Layout are layed out horizontally one after the other. Only thing can be controlled using the android:layout_gravity is how a child view is positioned vertically.

In the above example the top Linear Layout is a horizontal Linear Layout. Setting the android:layout_gravity=top on the l_g=top Button has an effect of positioning it at the top. Setting the android:layout_gravity=center on the l_g=center Button has an effect of positioning it at the vertical center. Setting the android:layout_gravity=bottom on the l_g=bottom Button has an effect of positioning it at the bottom.

For a vertical Linear Layout the following values make sense:
  • left
  • center
  • right
That is because the children of a vertical Linear Layout are layed out vertically one below the other. Only thing can be controlled using the android:layout_gravity is how a child view is positioned horizontally.

In the about example the bottom Linear Layout is a vertical Linear Layout. Setting the android:layout_gravity=left on the l_g=left Button has an effect of positioning it at the left. Setting the android:layout_gravity=center on the l_g=center Button has an effect of positioning it at the horizontal center. Setting the android:layout_gravity=right on the l_g=right Button has an effect of positioning it at the right.

Wednesday, December 23, 2009

Mac Win Man - a unified Mac OS X Desktop Window and Application Manager

  • Hide/Unhide Application
  • Minimize/Unminimize Window
  • Show window with same action no matter it was minimized or hidden
  • Zoom/Unzoom Window
  • Move and Resize windows using keyboard and mouse
    • Resize windows by dragging on the window edges and corners
    • Snap window to edges and center of the display using keystrokes
    • Precisely position and size the windows by entering the location and size values
  • Tile Windows Vertically
  • Tile Windows Horizontally
  • Cascade Windows
  • Close Window
  • Quit Application
Now works with multiple displays.

Screenshots

Switcher (Command TAB replacement)


Move and Resize using mouse and keyboard


Read more and Download...

Friday, October 16, 2009

TIP:Applescript to invoke All Windows function of Exposé and bind it to key you please

Here is the applescript to invoke the All Windows function of Exposé :
on run
-- delay is needed so that keybindings defined in
-- tools like Fastscripts works
delay 0.1
tell application "System Events"
-- 101 is key code for F9 key
key code 101
end tell
end run
Assuming you have bound Exposé:All Windows function to F9 key.

So you say - what is the big deal?

Well, if you look at System Preferences... > Exposé and Spaces pane > Exposé Tab , you will see that it allows you to bind various functions to limited set of keys. The script enables you to bind it to any key such as Option+Tab. How? Heres how:

Save the above script in ~/Library/Scripts/Expose.app . Then bind it to Option+Tab using Quicksilver or Launchbar or Fastscripts.

Saturday, October 03, 2009

Un-minimize minimized windows and bring them to front using Applescript

While implementing the AWS tool that I talked about in the last post - I learned a cool new Applescript technique to unminimize minimized windows. Here it is:

-- assuming you have name of a minimized window
set theWindowName to ....

-- is it minimized?
if (value of attribute "AXMinimized" of window theWindowName is true) then
-- first un-minimize the window
value of attribute "AXMinimized" of window theWindowName to false
end if

-- raise it
perform action "AXRaise" of window theWindowName

I had not much documentation on attributes such as "AXMinimized" and perform action "AXRaise".

Friday, October 02, 2009

Ruby on Rails : Injecting routes from a separate file

I am currently working on a Ruby on Rails (RoR) application and needed a mechanism to load routes that are generated into a file by another tool. After some experimentation I came up with the following solution.

In a Ruby on Rails application the routing is configured using the config/routes.rb file. The routes are defined using the draw method of ActionController::Routing::Routes class like this:
ActionController::Routing::Routes.draw do |map|
...
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
The block is executed with a local variable map in the scope. I wanted to insert routes defined in a separate file that is generated by another tool. To do that I tried to use the load or require methods. However I realized that it will not work because the load or require methods reset the scope to the top level. So I came up with the following:


# insert routes from generated file
instance_eval(File.read(File.expand_path(File.dirname(__FILE__)) + "/generated-routes.rb"))


Basically it is evaluating the contents of a file in the instance (current) scope. The File.expand_path(File.dirname(__FILE__)) simply computes the path to folder that contains routes.rb file. To that I append the name of generated routes file which lives next to routes.rb file.

Is there a better/idiomtic way to do this?

AWS - a unified Application and Window Switcher i.e. a Command TAB alternative

My other pet peeve with Mac OS X is how it deals differently with Applications and Windows that are minimized or hidden when one navigates using Command TAB( TAB)/Command Shift Tab ( TAB).

When on asked about any alternatives to the IMHO broken Command Tab behavior, frequently Mac-heads respond condescendingly about:

For me it does not matter if it is a window or application...I want to be able to switch to various windows where I want to work - hidden, minimized or what ever. Using Command TAB ( TAB)/Command Shift Tab ( TAB) to switch between applications and Command ~ ( ~)/Command Shift ~ ( ~) to switch between windows of an application is just plain wrong.

Once again, I was aggravated enough to make me write a tool to address just those issue. I wrote the AWS tool.

Read more...

Thursday, May 28, 2009

A Swing component to display last keystroke and keystroke history

A Swing component to display last keystroke. Also shows the keystroke history.

How it works

The KeyLabel component registers a global listener for KeyEvents using:
Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
On receiving KEY_RELEASED event formats the KeyStroke as a string and displays it. The dropdown shows history of last 100 keystrokes. Clicking on the X (Clear KeyStroke History) button clears the keystroke history. The KeyEvent listening can be suspended by deseleting the checkbox.

Usage
JComponent keyLabel = KeyLabelFactory.createKeyLabel();
// Use keyLabel in your application's statusbar
Demo

Download (KeyLabel.jar)
> java -jar KeyLabel.jar
Screenshot of KeyLabel Demo



Source Code

Wednesday, May 27, 2009

Error launching Mozilla (only from inside Eclipse) using simple Runtime.exec() on Ubuntu.

I discovered that, on Ubuntu 9.04, I cannot launch mozilla browser using the simple invocation of Runtime.getRuntime().exec("/usr/bin/mozilla"). It turns out, I have to use the variant of exec() where I can pass in some environment variables explicitly.

Here is the program that I used to test it:
import java.io.IOException;

public class MB {

/**
* @param args
*/
public static void main(String[] args) {
try {
Process exec = Runtime.getRuntime().exec("/usr/bin/mozilla"
// Uncommenting out following line will launch mozilla browser on Ubuntu
//, new String[] {"DISPLAY=:0.0", "HOME="+System.getProperty("user.home")}
);
System.out.println(exec.waitFor());
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
Very interesting. May be that is why Eclipse has trouble launching help in default external browser on Ubuntu.

UPDATE: It turns out that this fails only if I run the above program from inside Eclipse. If I run it from a terminal window it works. It turns out that Eclipse sets an environment variable MOZILLA_FIVE_HOME to point to /usr/lib[64]/xulrunner-addon to make the SWT's embedded browser widget work correctly. However this environment variable is inherited by any process that is launched from within Eclipse. And apparently MOZILLA_FIVE_HOME inteferes with the Mozilla browser (/usr/bin/mozilla) launch.

Two issues have been filed in Eclipse Bugzilla:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=278415
https://bugs.eclipse.org/bugs/show_bug.cgi?id=278296

Sunday, May 17, 2009

MultiPage Editor Tab Traverse Eclipse Plug-in

The MultiPage editors such as plug-in manifest editor do not support navigation of tabs (pages of the editor) using keyboard. This plug-in implements that functionality for any MultiPage editor that subclasses org.eclipse.ui.part.MultiPageEditorPart and uses org.eclipse.swt.custom.CTabFolder to implement the tab folder.

Screenshots:

Starting with Overview tab:



Type CTRL+TAB to go to Dependencies tab:



Type CTRL+SHIFT+TAB instead to go to build.properties tab:

Saturday, April 25, 2009

Move and Resize windows on Mac OS X

I have been always extremely annoyed by the fact that one cannot resize the windows on Mac OS X using all four edges of the window. In fact that is one of the most aggravating thing for me about using a Mac. Another issue is that one cannot use the keyboard to move and resize the windows. I was aggravated enough to make me write a tool to address just those issue. I wrote the MoveResize tool. It make synergistic use of Applescript and Java to fix IMHO a major usability flaw in Mac OS.

How it works (Swing version)

The implementation uses Applescript to get the frontmost window and it's bound. It sends the bounds rectangle to a server implemented in Java over a socket connection. The Java server takes the screen shot of the full Desktop and uses it as the Image label (a JLabel with ImageIcon) as the content pane of an undecorated JFrame which has the same bounds as the Desktop. A JPanel with semitransparent background and a dark rounded rectangular border is given the same bounds that were received over the socket. This JPanel is added to the PALETTE_LAYER of the JFrame's layered pane - which makes it appear floating in front of the front window. Mouse and Key listeners on the JPanel allows moving and resizing of the JPanel. When the user types the ENTER key the JFrame is hidden and the new bounds of the JPanel are sent back to the Applescript over the socket connection which moves and resizes the frontmost window.

Initially I had implemented the original version using SWT. However, it turns out that it is implementable in Swing also - once again proving that Swing is a very good toolkit. Added advantage is that Swing is part of the JDK making the implementation much much smaller. BTW the Swing implementation is much faster and plays nicely with log off and shutdown.

Watch Screencast


Here is a screenshot:



Saturday, April 18, 2009

Wednesday, April 15, 2009

Check out the Mac OS X Finder and Terminal scripts here.



Screencast

Sunday, March 29, 2009

Sampler Eclipse Plug-in

Check out the Sampler Eclipse Plug-in. The sampler plug-in adds a Color Sampler Toolbar. Color of any pixel on the desktop can be sampled by simply dragging the cursor from the Color Sampler label and copied to the clipboard in various formats as shown in the pop-up menu.

Saturday, March 21, 2009

Reverse Text Selection Eclipse Plug-in

Check out the Reverse Text Selection Eclipse Plug-in.

The following screencast shows how you can start with a initial selection and then extend it in both directions using the Reverse Text Selection command (Alt+Shift+/).

Thursday, March 12, 2009