2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.ide
.actions
;
18 import com
.intellij
.Patches
;
19 import com
.intellij
.ide
.BrowserUtil
;
20 import com
.intellij
.ide
.DataManager
;
21 import com
.intellij
.ide
.IdeBundle
;
22 import com
.intellij
.openapi
.actionSystem
.AnAction
;
23 import com
.intellij
.openapi
.actionSystem
.AnActionEvent
;
24 import com
.intellij
.openapi
.actionSystem
.PlatformDataKeys
;
25 import com
.intellij
.openapi
.application
.ApplicationInfo
;
26 import com
.intellij
.openapi
.application
.ApplicationNamesInfo
;
27 import com
.intellij
.openapi
.application
.ex
.ApplicationInfoEx
;
28 import com
.intellij
.openapi
.project
.DumbAware
;
29 import com
.intellij
.openapi
.util
.IconLoader
;
30 import com
.intellij
.openapi
.util
.SystemInfo
;
31 import com
.intellij
.openapi
.util
.text
.StringUtil
;
32 import com
.intellij
.openapi
.wm
.WindowManager
;
33 import com
.intellij
.ui
.LicenseeInfoProvider
;
34 import com
.intellij
.util
.ImageLoader
;
35 import com
.intellij
.util
.ui
.UIUtil
;
36 import org
.jetbrains
.annotations
.NonNls
;
40 import java
.awt
.event
.*;
41 import java
.text
.DateFormat
;
42 import java
.util
.ArrayList
;
43 import java
.util
.Calendar
;
44 import java
.util
.List
;
45 import java
.util
.Properties
;
47 public class AboutAction
extends AnAction
implements DumbAware
{
48 @NonNls private static final String COMPANY_URL
= "http://www.jetbrains.com/"; // TODO move to ApplicationInfo.xml
50 public void update(AnActionEvent e
) {
51 e
.getPresentation().setVisible(!SystemInfo
.isMacSystemMenu
);
52 e
.getPresentation().setDescription("Show information about " + ApplicationNamesInfo
.getInstance().getFullProductName());
55 public void actionPerformed(AnActionEvent e
) {
56 Window window
= WindowManager
.getInstance().suggestParentWindow(e
.getData(PlatformDataKeys
.PROJECT
));
58 showAboutDialog(window
);
61 public static void showAbout() {
62 Window window
= WindowManager
.getInstance().suggestParentWindow(
63 PlatformDataKeys
.PROJECT
.getData(DataManager
.getInstance().getDataContext()));
65 showAboutDialog(window
);
68 private static void showAboutDialog(Window window
) {
69 ApplicationInfoEx appInfo
= (ApplicationInfoEx
)ApplicationInfo
.getInstance();
70 JPanel mainPanel
= new JPanel(new BorderLayout());
71 final JComponent closeListenerOwner
;
72 if (appInfo
.showLicenseeInfo()) {
73 final Image image
= ImageLoader
.loadFromResource(appInfo
.getAboutLogoUrl());
74 final InfoSurface infoSurface
= new InfoSurface(image
);
75 infoSurface
.setPreferredSize(new Dimension(image
.getWidth(null), image
.getHeight(null)));
76 mainPanel
.add(infoSurface
, BorderLayout
.NORTH
);
78 closeListenerOwner
= infoSurface
;
81 mainPanel
.add(new JLabel(IconLoader
.getIcon(appInfo
.getAboutLogoUrl())), BorderLayout
.NORTH
);
82 closeListenerOwner
= mainPanel
;
86 if (window
instanceof Dialog
) {
87 dialog
= new JDialog((Dialog
)window
);
90 dialog
= new JDialog((Frame
)window
);
92 dialog
.setUndecorated(true);
93 dialog
.setContentPane(mainPanel
);
94 dialog
.addKeyListener(new KeyAdapter() {
95 public void keyPressed(KeyEvent e
) {
96 if (e
.getKeyCode() == KeyEvent
.VK_ESCAPE
&& e
.getModifiers() == 0) {
102 final long showTime
= System
.currentTimeMillis();
103 final long delta
= Patches
.APPLE_BUG_ID_3716865 ?
100 : 0;
105 dialog
.addWindowFocusListener(new WindowFocusListener() {
106 public void windowGainedFocus(WindowEvent e
) {}
108 public void windowLostFocus(WindowEvent e
) {
109 long eventTime
= System
.currentTimeMillis();
110 if (eventTime
- showTime
> delta
&& e
.getOppositeWindow() != e
.getWindow()) {
116 closeListenerOwner
.addMouseListener(new MouseAdapter() {
117 public void mouseClicked(MouseEvent e
) {
118 if (!e
.isConsumed()) {
127 dialog
.setLocationRelativeTo(window
);
128 dialog
.setVisible(true);
131 private static class AboutBoxLine
{
132 private final String myText
;
133 private final boolean myBold
;
134 private final boolean myLink
;
136 public AboutBoxLine(final String text
, final boolean bold
, final boolean link
) {
142 public AboutBoxLine(final String text
) {
149 public String
getText() {
153 public boolean isBold() {
157 public boolean isLink() {
162 private static class InfoSurface
extends JPanel
{
165 private final Image myImage
;
167 private Font myBoldFont
;
168 private final List
<AboutBoxLine
> myLines
= new ArrayList
<AboutBoxLine
>();
171 private int linkWidth
;
172 private boolean inLink
= false;
174 public InfoSurface(Image image
) {
179 //col = new Color(0xfa, 0xfa, 0xfa, 200);
181 linkCol
= Color
.blue
;
183 ApplicationInfoEx ideInfo
= (ApplicationInfoEx
)ApplicationInfo
.getInstance();
184 Calendar cal
= ideInfo
.getBuildDate();
185 myLines
.add(new AboutBoxLine(ideInfo
.getFullApplicationName(), true, false));
186 myLines
.add(new AboutBoxLine(IdeBundle
.message("aboutbox.build.number", ideInfo
.getBuild().asString())));
187 myLines
.add(new AboutBoxLine(IdeBundle
.message("aboutbox.build.date", DateFormat
.getDateInstance(DateFormat
.LONG
).format(cal
.getTime()))));
188 myLines
.add(new AboutBoxLine(""));
189 LicenseeInfoProvider provider
= LicenseeInfoProvider
.getInstance();
190 if (provider
!= null) {
191 myLines
.add(new AboutBoxLine(provider
.getLicensedToMessage(), true, false));
192 myLines
.add(new AboutBoxLine(provider
.getLicenseRestrictionsMessage()));
194 myLines
.add(new AboutBoxLine(""));
197 final Properties properties
= System
.getProperties();
198 myLines
.add(new AboutBoxLine(IdeBundle
.message("aboutbox.jdk", properties
.getProperty("java.version", "unknown")), true, false));
199 myLines
.add(new AboutBoxLine(IdeBundle
.message("aboutbox.vm", properties
.getProperty("java.vm.name", "unknown"))));
200 myLines
.add(new AboutBoxLine(IdeBundle
.message("aboutbox.vendor", properties
.getProperty("java.vendor", "unknown"))));
202 myLines
.add(new AboutBoxLine(""));
203 myLines
.add(new AboutBoxLine("JetBrains s.r.o.", true, false));
204 myLines
.add(new AboutBoxLine(COMPANY_URL
, true, true));
205 addMouseListener(new MouseAdapter() {
206 public void mousePressed(MouseEvent event
) {
209 BrowserUtil
.launchBrowser(COMPANY_URL
);
213 addMouseMotionListener(new MouseMotionAdapter() {
214 public void mouseMoved(MouseEvent event
) {
216 event
.getPoint().x
> linkX
&& event
.getPoint().y
>= linkY
&&
217 event
.getPoint().x
< linkX
+ linkWidth
&& event
.getPoint().y
< linkY
+ 10
220 setCursor(Cursor
.getPredefinedCursor(Cursor
.HAND_CURSOR
));
226 setCursor(Cursor
.getDefaultCursor());
235 protected void paintChildren(Graphics g
) {
236 super.paintChildren(g
);
237 Graphics2D g2
= (Graphics2D
)g
;
239 Font labelFont
= UIUtil
.getLabelFont();
240 for (int labelSize
= 10; labelSize
!= 6; labelSize
-= 1) {
242 g2
.drawImage(myImage
, 0, 0, this);
245 TextRenderer renderer
= new TextRenderer(0, 145, 398, 120, g2
);
246 g2
.setComposite(AlphaComposite
.Src
);
247 myFont
= labelFont
.deriveFont(Font
.PLAIN
, labelSize
);
248 myBoldFont
= labelFont
.deriveFont(Font
.BOLD
, labelSize
+1);
250 renderer
.render (75, 0, myLines
);
253 catch (TextRenderer
.OverflowException _
) {
259 public class TextRenderer
{
260 private final int xBase
;
261 private final int yBase
;
264 private final Graphics2D g2
;
268 private FontMetrics fontmetrics
;
269 private int fontAscent
;
270 private int fontHeight
;
273 public class OverflowException
extends Exception
{ }
275 public TextRenderer(final int xBase
, final int yBase
, final int w
, final int h
, final Graphics2D g2
) {
282 if (SystemInfo
.isWindows
) {
283 g2
.setRenderingHint(RenderingHints
.KEY_ANTIALIASING
, RenderingHints
.VALUE_ANTIALIAS_OFF
);
289 public void render(int indentX
, int indentY
, List
<AboutBoxLine
> lines
) throws OverflowException
{
292 g2
.setColor(Color
.black
);
293 for (int i
= 0; i
< lines
.size(); i
++) {
294 AboutBoxLine line
= lines
.get(i
);
295 final String s
= line
.getText();
296 setFont (line
.isBold() ? myBoldFont
: myFont
);
298 g2
.setColor(linkCol
);
300 linkY
= yBase
+ y
- fontAscent
;
301 FontMetrics metrics
= g2
.getFontMetrics(font
);
302 linkWidth
= metrics
.stringWidth (s
);
304 renderString(s
, indentX
);
305 if (i
== lines
.size()-2) {
308 else if (i
< lines
.size()-1) {
309 lineFeed (indentX
, s
);
314 private void renderString(final String s
, final int indentX
) throws OverflowException
{
315 final List
<String
> words
= StringUtil
.split(s
, " ");
316 for (String word
: words
) {
317 int wordWidth
= fontmetrics
.stringWidth(word
);
318 if (x
+ wordWidth
>= w
) {
319 lineFeed(indentX
, word
);
323 final int cW
= fontmetrics
.charWidth(c
);
325 g2
.drawChars(new char[]{c
}, 0, 1, xBase
+ x
, yBase
+ y
);
329 renderWord(word
, indentX
);
333 private void renderWord(final String s
, final int indentX
) throws OverflowException
{
334 for (int j
= 0; j
!= s
.length(); ++ j
) {
335 final char c
= s
.charAt(j
);
336 final int cW
= fontmetrics
.charWidth(c
);
338 lineFeed(indentX
, s
);
340 g2
.drawChars(new char[]{c
}, 0, 1, xBase
+ x
, yBase
+ y
);
345 private void lineFeed(int indent
, final String s
) throws OverflowException
{
347 if (s
.length() == 0) {
354 throw new OverflowException();
357 private void setFont(Font font
) {
359 fontmetrics
= g2
.getFontMetrics(font
);
361 fontAscent
= fontmetrics
.getAscent();
362 fontHeight
= fontmetrics
.getHeight();