The Source for Java Technology Collaboration
User: Password:



Kirill Grouchnikov's Blog

January 2007 Archives


Ye old faithful IDE

Posted by kirillcool on January 18, 2007 at 10:03 AM | Permalink | Comments (15)

My current work project involves extending an existing application and adding a few new features. All is well and good, but it's written in C++. Well, all is still well, since that has been my primary development from '99 to '02 (in Visual Studio 6). The code is written well, the original developers sit right next to me, C++ is very much like Java (thankfully they didn't use operator overloading), so what's the problem?

Well, it all begins with the build configuration. Since there's no such thing as an Ant build script, you have all these in the project files (.sln and .vcproj). Now, the structure of these files changes between different Visual Studio versions, so if you want to upgrade to Visual Studio 2005, you'll have to upgrade your projects files as well. In this specific case, this is way over my head, since the build portions are very complicated and it would take too much time to port it to VS 2005.

So, i'm stuck with 4-year old IDE. Now, back in the day (VS 6.0), i didn't notice it, but now, coming back from Eclipse / NetBeans / IDEA, this looks like an old relic from The Stone Age. Refactoring? Not yet. Find all uses? Not yet. Set breakpoint on field change? Just follow this sequence of 7-8 steps that involves writing down the field address and typing it later in some obscure screen. And the list goes on. Personally, i came to depend so much on key strokes in Eclipse, that coming back to an IDE that doesn't have the matching functionality is a serious shock.

Now, this is obviously not a VS problem. This would be the same with much earlier versions of Eclipse, NetBeans and JBuilder. It's just that the coding doesn't really flow. If you want to add a new parameter to a method and change all the callers, you have the following options, none of which are very attractive:

  • Ctrl+Shift+F (Find in Files) for the method name and hope that no other class defines the same method name. Depending on the soltion size, this takes some time (the results are not cached by IDE).
  • Change the .h and .cpp by adding a letter to the method name, build the solution and see all the places that have been broken. Depending on the solution size and build target complexities, this takes even more time.

With this, an extended "Thank You" goes to all Java IDE developers that continue adding new features to their IDEs. It's only when we stop using them, we can fully appreciate their advantages.



Playing with Color

Posted by kirillcool on January 17, 2007 at 09:40 AM | Permalink | Comments (12)

Seeing that this subject has popped up twice over the last two days (here and here), i decided to share a little trick to make a Color object mutable.

In general, the Color class doesn't allow changing the existing object. However, since it's not final, we can use the Delegate pattern and direct all methods to a single "master" color that is computed dynamically. The master color computation can depend, for example, on rollover state (illustrated below) which will allow creating rollover effects without triggering the property change events (on the "foregroundColor" property).

Here is how it's done.

public class RolloverForeground extends JFrame {

  public RolloverForeground() {
    this.setLayout(new FlowLayout());

    final JButton button = new JButton("sample");
    button.setForeground(new Color(0x000000) {
      private Color getDelegate() {
        return button.getModel().isRollover() ? Color.red : Color.black;
      }

      @Override
      public Color brighter() {
        return getDelegate().brighter();
      }

      @Override
      public synchronized PaintContext createContext(ColorModel cm,
          Rectangle r, Rectangle2D r2d, AffineTransform xform,
          RenderingHints hints) {
        return getDelegate().createContext(cm, r, r2d, xform, hints);
      }

      @Override
      public Color darker() {
        return getDelegate().darker();
      }

      @Override
      public boolean equals(Object obj) {
        return getDelegate().equals(obj);
      }

      @Override
      public int getAlpha() {
        return getDelegate().getAlpha();
      }

      @Override
      public int getBlue() {
        return getDelegate().getBlue();
      }

      @Override
      public float[] getColorComponents(ColorSpace cspace,
          float[] compArray) {
        return getDelegate().getColorComponents(cspace, compArray);
      }

      @Override
      public float[] getColorComponents(float[] compArray) {
        return getDelegate().getColorComponents(compArray);
      }

      @Override
      public ColorSpace getColorSpace() {
        return getDelegate().getColorSpace();
      }

      @Override
      public float[] getComponents(ColorSpace cspace, float[] compArray) {
        return getDelegate().getComponents(cspace, compArray);
      }

      @Override
      public float[] getComponents(float[] compArray) {
        return getDelegate().getComponents(compArray);
      }

      @Override
      public int getGreen() {
        return getDelegate().getGreen();
      }

      @Override
      public int getRed() {
        return getDelegate().getRed();
      }

      @Override
      public int getRGB() {
        return getDelegate().getRGB();
      }

      @Override
      public float[] getRGBColorComponents(float[] compArray) {
        return getDelegate().getRGBColorComponents(compArray);
      }

      @Override
      public float[] getRGBComponents(float[] compArray) {
        return getDelegate().getRGBComponents(compArray);
      }

      @Override
      public int getTransparency() {
        return getDelegate().getTransparency();
      }
    });

    this.add(button);
    button.getModel().addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        button.repaint();
      }
    });

    this.setSize(200100);
    this.setLocationRelativeTo(null);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }

  public static void main(String[] argsthrows Exception {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        new RolloverForeground().setVisible(true);
      }
    });
  }
}

The most interesting part is the getDelegate method in our foreground color. It returns black or red depending on the rollover state of the model. All the Color methods use this color, delegating the real implementation to it. Screenshot of the application in default state:

default.png

Screenshot of the application in rollover state:

rollover.png

Note that this technique can be easily extended to smoothly animate the foreground color from black to red without triggering property change events along the way.



Where have i been?

Posted by kirillcool on January 12, 2007 at 10:13 AM | Permalink | Comments (10)

My last blog entry was back in November and it marked the last major core feature added to the Iowa release of Substance look and feel. The 45 days since were spent on one of the more important and less rewarding tasks in open source development - documentation.

Some choose to charge money for documentation of their open source projects. Some prefer not to write any (saying that the code is the best documentation). Some cram as much as possible into Javadocs and use custom doclets to generate tons of "documentation". Personally, none of the above works for me.

So, the result of these 45 days is:

  • 118 sample standalone applications (available in test.samples package in the Substance distribution).
  • 206 screenshots.
  • 135 inter-linked documentation pages with formatted code, screenshots and explanations.

These represent complete documentation for Substance API, Substance client properties and laf-widget client properties. Each code sample is a complete standalone (except icon loading) application which shows either a single or a logical group of 2-3 related API calls / client properties.

This effort has been partially inspired by the documentation of the excellent Quaqua look-and-feel, as well as by the user requests on particular feature use (this month the number of private e-mails for this project has reached 2500 mark).

The next release is planned on February 4th and i'd like to extend my thanks for all the bug reports (especially to qu0ll), testing ans using Substance. I'm also pleased to say searching for java look and feel in MSN Live search puts Substance at the first spot (in Google it's 4th and in Yahoo it's 9th):

live-search.png

I've been tagged...

Posted by kirillcool on January 04, 2007 at 01:54 PM | Permalink | Comments (0)

Joshua has tagged me, so here are five things that you didn't know about me.
  1. I spent about 25 minutes (don't tell my boss) trying to trace this thing to its origin. I got through 49 (!!!) links (some had to be retrieved from Yahoo's cache) to this post which mentions some mysterious Prousty (there's no link). Apparently, i'm not the only one who got to that Prousty. Think he's real?
  2. I waited to get tagged (thanks Josh) unlike some who just jumped in without the invitation and get credited for starting it.
  3. I spent an additional minute with a calculator. The current projected world population is just above 5^14. Apparently there are enough sane people in the world not to pass it on.
  4. I'm really glad it's only five and not a hundred.
  5. Although i don't agree with the language, i do agree with the message. Kind of contradictory to this whole post, i know.
And now on to Patrick, Luan, Jonathan, Bill and Hani himself.



Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds