Implement a tool window on the right in IntelliJ.

Summary:
Launch the plugin and you can see a panel window on the right.
By clicking refresh you can see a list of targets fetched.
By double clicking one target, it will build.
diff --git a/plugin/src/com/facebook/buck/plugin/intellij/BuckPluginComponent.java b/plugin/src/com/facebook/buck/plugin/intellij/BuckPluginComponent.java
index afc1217..5bab225 100644
--- a/plugin/src/com/facebook/buck/plugin/intellij/BuckPluginComponent.java
+++ b/plugin/src/com/facebook/buck/plugin/intellij/BuckPluginComponent.java
@@ -22,6 +22,7 @@
 import com.facebook.buck.plugin.intellij.commands.SocketClient.BuckPluginEventListener;
 import com.facebook.buck.plugin.intellij.commands.TargetsCommand;
 import com.facebook.buck.plugin.intellij.commands.event.Event;
+import com.facebook.buck.plugin.intellij.ui.BuckUI;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
@@ -36,6 +37,7 @@
   private final Project project;
   private final EventListener listener;
   private Optional<BuckRunner> buckRunner;
+  private BuckUI buckUI;
 
   public BuckPluginComponent(Project project) {
     this.project = Preconditions.checkNotNull(project);
@@ -45,6 +47,7 @@
 
   @Override
   public void projectOpened() {
+    buckUI = new BuckUI(this);
     if (buckRunner.isPresent()) {
       buckRunner.get().launchBuckd();
     }
@@ -67,6 +70,10 @@
     return "BuckComponent";
   }
 
+  public Project getProject() {
+    return project;
+  }
+
   public void setBuckDirectory(Optional<String> buckDirectory) {
     Preconditions.checkNotNull(buckDirectory);
     try {
@@ -84,7 +91,7 @@
   }
 
   private void reportBuckNotPresent() {
-    // TODO(user) Show error message to UI
+    buckUI.showErrorMessage("Buck not found");
   }
 
   public void refreshTargetsList() {
@@ -96,7 +103,7 @@
           BackgroundFromStartOption.getInstance()) {
         public void run(ProgressIndicator progressIndicator) {
           ImmutableList<BuckTarget> targets = TargetsCommand.getTargets(buckRunner);
-          // TODO(user) Refresh UI to show targets
+          buckUI.updateTargets(targets);
         }
       };
       task.queue();
diff --git a/plugin/src/com/facebook/buck/plugin/intellij/ui/BuckTargetsPanel.form b/plugin/src/com/facebook/buck/plugin/intellij/ui/BuckTargetsPanel.form
new file mode 100644
index 0000000..059a091
--- /dev/null
+++ b/plugin/src/com/facebook/buck/plugin/intellij/ui/BuckTargetsPanel.form
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.facebook.buck.plugin.intellij.ui.BuckTargetsPanel">
+  <grid id="27dc6" binding="targetsPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="0" vgap="0">
+    <margin top="2" left="2" bottom="2" right="2"/>
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none">
+      <size top="0" left="3" bottom="3" right="3"/>
+    </border>
+    <children>
+      <scrollpane id="8bbd6">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <component id="42c00" class="javax.swing.JList" binding="targetsList" custom-create="true">
+            <constraints/>
+            <properties/>
+          </component>
+        </children>
+      </scrollpane>
+      <toolbar id="faed" binding="toolBar">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
+            <preferred-size width="-1" height="20"/>
+          </grid>
+        </constraints>
+        <properties>
+          <floatable value="false"/>
+        </properties>
+        <border type="none"/>
+        <children>
+          <component id="ca591" class="javax.swing.JButton" binding="refreshTargetsButton" custom-create="true">
+            <constraints/>
+            <properties>
+              <text value="Refresh"/>
+              <toolTipText value="Refresh targets"/>
+            </properties>
+          </component>
+          <component id="6d0c6" class="javax.swing.JButton" binding="cleanButton" custom-create="true" default-binding="true">
+            <constraints/>
+            <properties>
+              <text value="Clean"/>
+            </properties>
+          </component>
+        </children>
+      </toolbar>
+    </children>
+  </grid>
+</form>
diff --git a/plugin/src/com/facebook/buck/plugin/intellij/ui/BuckTargetsPanel.java b/plugin/src/com/facebook/buck/plugin/intellij/ui/BuckTargetsPanel.java
new file mode 100644
index 0000000..08e8671
--- /dev/null
+++ b/plugin/src/com/facebook/buck/plugin/intellij/ui/BuckTargetsPanel.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2013-present Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.facebook.buck.plugin.intellij.ui;
+
+import com.facebook.buck.plugin.intellij.BuckPluginComponent;
+import com.facebook.buck.plugin.intellij.BuckTarget;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.intellij.ui.components.JBList;
+
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+
+import javax.swing.*;
+
+public class BuckTargetsPanel {
+
+  public static String DISPLAY_NAME = "Targets";
+
+  private BuckPluginComponent component;
+  private JPanel targetsPanel;
+  private JList targetsList;
+  private JButton refreshTargetsButton;
+  private JToolBar toolBar;
+  private JButton cleanButton;
+
+  public BuckTargetsPanel(BuckPluginComponent component) {
+    this.component = Preconditions.checkNotNull(component);
+  }
+
+  public JPanel getPanel() {
+    return targetsPanel;
+  }
+
+  private void createUIComponents() {
+    targetsList = Preconditions.checkNotNull(createTargetsList());
+
+    refreshTargetsButton = createToolbarIcon();
+    refreshTargetsButton.addActionListener(new ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        component.refreshTargetsList();
+      }
+    });
+
+    cleanButton = createToolbarIcon();
+    cleanButton.addActionListener(new ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        component.clean();
+      }
+    });
+  }
+
+  private JButton createToolbarIcon() {
+    JButton button = new JButton();
+    return button;
+  }
+
+  private JList createTargetsList() {
+    final JBList targetsList = new JBList(new TargetsListModel(ImmutableList.<BuckTarget>of()));
+    targetsList.setCellRenderer(new DefaultListCellRenderer() {
+      @Override
+      public Component getListCellRendererComponent(JList list,
+                                                    Object value,
+                                                    int index,
+                                                    boolean isSelected,
+                                                    boolean cellHasFocus) {
+        BuckTarget target = (BuckTarget) value;
+        Component renderer = super.getListCellRendererComponent(list,
+            target.getName(),
+            index,
+            isSelected,
+            cellHasFocus
+        );
+        ((JComponent) renderer).setToolTipText(target.getDescription());
+        return renderer;
+      }
+    });
+
+    final MouseListener mouseListener = new MouseAdapter() {
+      @Override
+      public void mouseClicked(MouseEvent e) {
+        if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
+          // Double click
+          BuckTarget target = (BuckTarget) targetsList.getSelectedValue();
+          component.buildTarget(target);
+        }
+      }
+    };
+    targetsList.addMouseListener(mouseListener);
+    return targetsList;
+  }
+
+  public void updateTargets(final ImmutableList<BuckTarget> targets) {
+    Preconditions.checkNotNull(targets);
+    EventQueue.invokeLater(new Runnable() {
+      @Override
+      public void run() {
+        targetsList.setModel(new TargetsListModel(targets));
+      }
+    });
+  }
+}
diff --git a/plugin/src/com/facebook/buck/plugin/intellij/ui/BuckUI.java b/plugin/src/com/facebook/buck/plugin/intellij/ui/BuckUI.java
new file mode 100644
index 0000000..8f4ea70
--- /dev/null
+++ b/plugin/src/com/facebook/buck/plugin/intellij/ui/BuckUI.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013-present Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.facebook.buck.plugin.intellij.ui;
+
+import com.facebook.buck.plugin.intellij.BuckPluginComponent;
+import com.facebook.buck.plugin.intellij.BuckTarget;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowAnchor;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentFactory;
+
+public class BuckUI {
+
+  public static final String BUCK_TOOL_WINDOW_ID = "Buck";
+
+  private BuckPluginComponent component;
+  private ToolWindow toolWindow;
+  private BuckTargetsPanel buckTargetsPanel;
+
+  public BuckUI(BuckPluginComponent component) {
+    this.component = Preconditions.checkNotNull(component);
+    createToolWindow();
+    createTargetsPanel();
+  }
+
+  private void createToolWindow() {
+    ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(component.getProject());
+    toolWindow = toolWindowManager.registerToolWindow(BUCK_TOOL_WINDOW_ID,
+        false, /* canClose */
+        ToolWindowAnchor.RIGHT
+    );
+    toolWindow.setIcon(AllIcons.Debugger.Threads);
+  }
+
+  private void createTargetsPanel() {
+    buckTargetsPanel = new BuckTargetsPanel(component);
+    Content content = ContentFactory.SERVICE.getInstance().createContent(
+        buckTargetsPanel.getPanel(),
+        buckTargetsPanel.DISPLAY_NAME,
+        false /* isLockable */
+    );
+    toolWindow.getContentManager().addContent(content);
+  }
+
+  public void showErrorMessage(String message) {
+    Preconditions.checkNotNull(message);
+    Messages.showErrorDialog(message, "Buck");
+  }
+
+  public void updateTargets(ImmutableList<BuckTarget> targets) {
+    Preconditions.checkNotNull(targets);
+    buckTargetsPanel.updateTargets(targets);
+  }
+}
diff --git a/plugin/src/com/facebook/buck/plugin/intellij/ui/TargetsListModel.java b/plugin/src/com/facebook/buck/plugin/intellij/ui/TargetsListModel.java
new file mode 100644
index 0000000..9c86d7d
--- /dev/null
+++ b/plugin/src/com/facebook/buck/plugin/intellij/ui/TargetsListModel.java
@@ -0,0 +1,33 @@
+package com.facebook.buck.plugin.intellij.ui;
+
+import com.facebook.buck.plugin.intellij.BuckTarget;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import javax.swing.AbstractListModel;
+
+public class TargetsListModel extends AbstractListModel {
+
+  private ImmutableList<BuckTarget> targets;
+
+  public TargetsListModel(ImmutableList<BuckTarget> targets) {
+    Preconditions.checkNotNull(targets);
+    setTargets(targets);
+  }
+
+  public void setTargets(ImmutableList<BuckTarget> targets) {
+    Preconditions.checkNotNull(targets);
+    this.targets = ImmutableList.copyOf(targets);
+    fireContentsChanged(this, 0 /* start index */ , this.targets.size() + 1 /* end index */);
+  }
+
+  @Override
+  public int getSize() {
+    return targets.size();
+  }
+
+  @Override
+  public Object getElementAt(int index) {
+    return targets.get(index);
+  }
+}