Atom Feed SITE FEED   ADD TO GOOGLE READER

Kwikr for Flickr

We haven't finished our ambitious Quickr project yet, but I still wanted to download all my Flickr photos at full resolution for use in an iPhoto project.

The solution was so simple it hurts. I needed:
  • A key for the Flickr web services API
  • Flickrj, a .jar file for connecting to said API
  • Kwikr.java, about 50 lines of Java code to download my photos

    When an open web service like Flickr Services and a powerful language like Java combine, life is good!
  • One Action for one clipboard

    In our app at work you can copy data to the clipboard from text fields, tables, graphs and probably more. The problem was that we needed 'cut', 'copy' and 'paste' actions in the Edit menu on the menu bar, and those actions needed to act upon different components when invoked at different times.

    Our solution: track the most recently focused component (that supports the clipboard), and direct the action to that component. It exploits the fact that TransferHandler.getXXXAction().actionPerformed() performs its work on the source of the received ActionEvent.

    Here's the code:
    /**
    * This class provides cut, copy and paste actions that act
    * upon the most recently focused component that supports these
    * actions.
    */
    public class ClipboardActionsProvider
    {
    /** use the focus manager to track the most recently focused component */
    private KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();

    /** The clipboard-capable JComponent that had the focus most recently */
    private JComponent latestSupported = null;

    /** a single instance for each clipboard action */
    private final Action cutAction = new CutAction();
    private final Action copyAction = new CopyAction();
    private final Action pasteAction = new PasteAction();

    public ClipboardActionsProvider() {
    focusManager.addPropertyChangeListener("focusOwner", new FocusOwnerListener());
    }

    public Action cutAction() { return cutAction; }
    public Action copyAction() { return copyAction; }
    public Action pasteAction() { return pasteAction; }

    private void handleFocusOwnerChange() {
    Component component = focusManager.getFocusOwner();
    if(component == latestSupported) return;

    // bail if this component can't participate in cut & paste
    if(!(component instanceof JComponent)) return;
    JComponent jComponent = (JComponent)component;
    if(jComponent.getTransferHandler() == null) return;

    // save this component for cut, copy and paste
    latestSupported = jComponent;
    }

    /**
    * When the focus is changed, update the latest supported component.
    */
    private class FocusOwnerListener implements PropertyChangeListener {
    public void propertyChange(PropertyChangeEvent evt) {
    handleFocusOwnerChange();
    }
    }

    /**
    * Invokes a cut, copy or paste as if it originated from
    * the most recent focus owner.
    */
    private class CutAction extends AbstractAction {
    public void actionPerformed(ActionEvent e) {
    TransferHandler.getCutAction().actionPerformed(new ActionEvent(latestSupported, e.getID(), e.getActionCommand(), e.getWhen(), e.getModifiers()));
    }
    }
    private class CopyAction extends AbstractAction {
    /** omitted, code is similar to CutAction */
    }
    private class PasteAction extends AbstractAction {
    /** omitted, code is similar to CutAction */
    }
    }