1. | Make a full system backup of the computer and system state. |
2. | Log on as an Administrator. |
3. | Start Regedt32.exe. |
4. | Go to the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices |
5. | Click MountedDevices. |
6. | On the Security menu, click Permissions. |
7. | Verify that Administrators have full control. Change this back when you are finished with these steps. |
8. | Quit Regedt32.exe, and then start Regedit.exe. |
9. | Locate the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices |
10. | Find the drive letter you want to change to (new). Look for "\DosDevices\C:". |
11. | Right-click \DosDevices\C:, and then click Rename. Note You must use Regedit instead of Regedt32 to rename this registry key. |
12. | Rename it to an unused drive letter "\DosDevices\Z:". This frees up drive letter C. |
13. | Find the drive letter you want changed. Look for "\DosDevices\D:". |
14. | Right-click \DosDevices\D:, and then click Rename. |
15. | Rename it to the appropriate (new) drive letter "\DosDevices\C:". |
16. | Click the value for \DosDevices\Z:, click Rename, and then name it back to "\DosDevices\D:". |
17. | Quit Regedit, and then start Regedt32. |
18. | Change the permissions back to the previous setting for Administrators (this should probably be Read Only). |
19. | Restart the computer. |
сряда, 29 август 2007 г.
Change the System/Boot Drive Letter
петък, 17 август 2007 г.
Rules of Thumb for Ajax Security
2. Check for SQL injections.
3. Check for JavaScript injections.
4. Keep the business logic on the server!
5. Don't assume every request is real!
6. Check the data with validation!
7. Look at the request's header information and make sure it is correct.
сряда, 8 август 2007 г.
JavaScript: Create and Delete Options from a Select Box
<form name="testform">
<select name="testselect">
<option value="first">first option</option>
<option value="second">second option</option>
<option value="third">third option</option>
<option>your browser can't handle this script</option>
</select>
</form>
To access options in a select box, you use the following code:
document.forms['testform'].testselect.options[i]
where i is the number of the option you want to access. Remember that the first option is options[0], the second one is options[1] etc.
Now if you want to delete the option, do
document.forms['testform'].testselect.options[i] = null;
By making it null, the option is completely removed from the list. Note that this also affects the numbering of the options. Suppose you remove option[1] from the example above, the old option[2] ('Third option') becomes option[1] etc.
To create a new option, do:
document.forms['testform'].testselect.options[i] = new Option('new text','new value');
where new text is the text the user sees and new value is the VALUE of the new option, the bit that's sent to the server when the form is submitted. Of course the new option overwrites the old one.
To completely clear a select box, do
document.forms['testform'].testselect.options.length = 0;
четвъртък, 2 август 2007 г.
How to make Apache run ASP.NET / ASP.NET 2.0
2. Install Microsoft.NET Framework and .NET Software Development Kit from here
3. Install the Apache Module: Mod AspDotNet from here
4. Make the following changes to the httpd.conf file of Apache (add at the end of the file):
5. Create a directory c:\SampleASP and insert the index.aspx in it.# ASP.NET start
LoadModule aspdotnet_module "modules/mod_aspdotnet.so"
AddHandler asp.net asax ascx ashx asmx aspx axd config cs csproj licx rem resources resx soap vb vbproj vsdisco webinfo
<IfModule mod_aspdotnet.cpp>
# Mount the ASP.NET /asp application
AspNetMount /SampleASP "c:/SampleASP"
# /SampleASP is the alias name for asp.net to execute
# "c:/SampleASP" is the actual execution of files/folders in that location
# Map all requests for /asp to the application files
Alias /SampleASP "c:/SampleASP"
# maps /SampleASP request to "c:/SampleASP"
# now to get to the /SampleASP type "http://localhost/SampleASP"
# It'll redirect to "c:/SampleASP"
# Allow asp.net scripts to be executed in the /SampleASP example
<Directory "c:/SampleASP">
Options FollowSymlinks ExecCGI
Order allow,deny
Allow from all
DirectoryIndex index.htm index.aspx
# default the index page to .htm and .aspx
</Directory>
# For all virtual ASP.NET webs, we need the aspnet_client files
# to serve the client-side helper scripts.
AliasMatch /aspnet_client/system_web/(\d+)_(\d+)_(\d+)_(\d+)/(.*) "C:/Windows/Microsoft.NET/Framework/v$1.$2.$3/ASP.NETClientFiles/$4"
<Directory "C:/Windows/Microsoft.NET/Framework/v*/ASP.NETClientFiles">
Options FollowSymlinks
Order allow,deny
Allow from all
</Directory>
</IfModule>
6. Restart apache server.
7. Open Explorer and navigate to http://localhost/SampleASP/index.aspx.
If everything worked fine you should get a nice ASP.NET page working.
сряда, 1 август 2007 г.
JAR files revealed
What is a JAR file?
The JAR file format is based on the popular ZIP file format, and is used for aggregating many files into one. Unlike ZIP files, JAR files are used not only for archiving and distribution, but also for deployment and encapsulation of libraries, components, and plug-ins, and are consumed directly by tools such as compilers and JVMs. Special files contained in the JAR, such as manifests and deployment descriptors, instruct tools how a particular JAR is to be treated.
A JAR file might be used:- For distributing and using class libraries
- As building blocks for applications and extensions
- As deployment units for components, applets, or plug-ins
- For packaging auxiliary resources associated with components
- Security. You can digitally sign the contents of a JAR file. Tools that recognize your signature can then optionally grant your software security privileges it wouldn't otherwise have, and detect if the code has been tampered with.
- Decreased download time. If an applet is bundled in a JAR file, the applet's class files and associated resources can be downloaded by a browser in a single HTTP transaction, instead of opening a new connection for each file.
- Compression. The JAR format allows you to compress your files for efficient storage.
- Transparent platform extension. The Java Extensions Framework provides a means by which you can add functionality to the Java core platform, which uses the JAR file for packaging of extensions. (Java 3D and JavaMail are examples of extensions developed by Sun.)
- Package sealing. Packages stored in JAR files can be optionally sealed to enforce version consistency and security. Sealing a package means that all classes defined in that package must be found in the same JAR file.
- Package versioning. A JAR file can hold data about the files it contains, such as vendor and version information.
- Portability. The mechanism for handling JAR files is a standard part of the Java platform's core API.
Compressed and uncompressed JARs
The jar
tool (see The jar
tool for details) compresses files by default. Uncompressed JAR files can generally be loaded more quickly than compressed JAR files, because the need to decompress the files during loading is eliminated, but download time over a network may be longer for uncompressed files.
Most JAR files contain a META-INF directory, which is used to store package and extension configuration data, such as security and versioning information. The following files or directories in the META-INF directory are recognized and interpreted by the Java 2 platform for configuring applications, extensions, and class loaders:
- MANIFEST.MF. The manifest file defines the extension- and package-related data.
- INDEX.LIST. This file is generated by the new
-i
option of thejar
tool and contains location information for packages defined in an application or extension. It is part of the JarIndex implementation and used by class loaders to speed up the class loading process. - xxx.SF. This is the signature file for the JAR file. The placeholder xxx identifies the signer.
- xxx.DSA. The signature block file associated with the signature file stores the public signature used to sign the JAR file.
To perform basic tasks with JAR files, you use the Java Archive Tool (jar
tool) provided as part of the Java Development Kit. You invoke the jar
tool with the jar
command. Table 1 shows some common applications:
Table 1. Common usages of the jar
tool
Function | Command |
Creating a JAR file from individual files | jar cf jar-file input-file... |
Creating a JAR file from a directory | jar cf jar-file dir-name |
Creating an uncompressed JAR file | jar cf0 jar-file dir-name |
Updating a JAR file | jar uf jar-file input-file... |
Viewing the contents of a JAR file | jar tf jar-file |
Extracting the contents of a JAR file | jar xf jar-file |
Extracting specific files from a JAR file | jar xf jar-file archived-file... |
Running an application packaged as an executable JAR file | java -jar app.jar |
An executable jar file is a self-contained Java application stored in a specially configured JAR file, which can be executed directly by the JVM without having to first extract the files or set up a class path. To run an application stored in a non-executable JAR, you have to add it to your class path and invoke the application's main class by name. But by using executable JAR files, we can run an application without extracting it or needing to know the main entry point. Executable JARs facilitate easy distribution and execution of Java applications.
Creating an executable JAR is easy. You begin by placing all your application code in a single directory. Let's say the main class in your application is com.mycompany.myapp.Sample
. You want to create a JAR file that contains the application code and identifies the main class. To do this, create a file called manifest
somewhere (not in your application directory), and add the following line to it:
Main-Class: com.mycompany.myapp.Sample |
|
java -jar
.An executable JAR must reference all the other dependent JARs it requires through the Class-Path
header of the manifest file. The environment variable CLASSPATH and any class path specified on the command line is ignored by the JVM if the -jar
option is used.
Now that we've packaged our application into an executable JAR called ExecutableJar.jar, we can launch the application directly from the file using the following command:
java -jar ExecutableJar.jar |
Sealing a package within a JAR file means that all classes defined in that package must be found in the same JAR file. This allows the package author to enforce version consistency among packaged classes. Sealing also provides a security measure to detect code tampering.
To seal a package, add a Name
header for the package, followed by a Sealed
header with value "true" to the JAR manifest file. Just as with executable JARs, you can seal a JAR by specifying a manifest file with the appropriate header elements when the JAR is created, as shown here:
Name: com/samplePackage/ |
Name
header identifies the package's relative pathname. It ends with a "/" to distinguish it from a filename. Any headers following a Name
header, without any intervening blank lines, apply to the file or package specified in the Name
header. In the example above, because the Sealed
header occurs after the Name
header without intervening blank lines, the Sealed
header will be interpreted as applying only to the package com/samplePackage
.If you try to load a class in a sealed package from another source other than the JAR file in which the sealed package lives, the JVM will throw a SecurityException
.
Extensions add functionality to the Java platform, and an extensions mechanism is built into the JAR file format. The Extensions mechanism allows JAR files to specify other required JAR files via the Class-Path
headers in the manifest file.
|
The JVM effectively automatically adds JARs referenced in a Class-Path
header to the class path when loading a JAR that uses the extension mechanism. However, the extension JAR path is interpreted as a relative path, so in general the extension JAR must be stored in the same directory as the JAR referencing it.
For example, assume the class ExtensionClient
, which references class ExtensionDemo
, is bundled in a JAR file called ExtensionClient.jar, and that the classExtensionDemo
is bundled in ExtensionDemo.jar. In order for ExtensionDemo.jar to be treated as an extension, ExtensionDemo.jar must be listed in the Class-Path
header in ExtensionClient.jar's manifest, as follows:
Manifest-Version: 1.0 |
Class-Path
header in this manifest is ExtensionDemo.jar with no path specified, indicating that ExtensionDemo.jar is located in the same directory as the ExtensionClient JAR file.A JAR file can be signed by using the
jarsigner
tool or directly through the java.security
API. A signed JAR file is exactly the same as the original JAR file, except that its manifest is updated, and two additional files are added to the META-INF directory, a signature file and a signature block file.A JAR file is signed using a certificate stored in the Keystore database. Certificates stored in the keystore are protected with a password, which must be provided to the jarsigner
tool to sign a JAR file.
Each signer of a JAR is represented by a signature file with the extension .SF within the META-INF directory of the JAR file. The format of the file is similar to the manifest file -- a set of RFC-822 headers. As shown below, it consists of a main section, which includes information supplied by the signer but not specific to any particular JAR file entry, followed by a list of individual entries which also must be present in the manifest file. To validate a file from a signed JAR, a digest value in the signature file is compared against a digest calculated against the corresponding entry in the JAR file.
Listing 1. Manifest and signature files in signed JARs
|
A digital signature is a signed version of the .SF
signature file. Digital signature files are binary files and have the same filename as the .SF
file but a different extension. The extension varies depending on the type of digital signature -- RSA, DSA, or PGP -- and on the type of certificate used to sign the JAR.
keystores
. The JDK contains tools for creating and modifying keystores. Each key in the keystore can be identified by an alias, which is typically the name of the signer who owns the key.All keystore entries (key and trusted certificate entries) are accessed with unique aliases. An alias is specified when you add an entity to the keystore using the keytool -genkey
command to generate a key pair (public and private key). Subsequent keytool
commands must use this same alias to refer to the entity.
For example, to generate a new public/private key pair with the alias "james" and wrap the public key into a self-signed certificate, you would use with the following command:
keytool -genkey -alias james -keypass jamespass |
keytool
will automatically create it.The
jarsigner
tool uses keystore to generate or verify digital signatures for JAR files.Assuming you've created the keystore "jamesKeyStore" as in the example above, and it contains a key with alias "james," you can sign a JAR file with the following command:
jarsigner -keystore jamesKeyStore -storepass jamesKeyStorePass |
The jarsigner
tool can also verify a signed JAR file; this operation is considerably simpler than signing the JAR file. Just execute the following command:
jarsigner -verify SSample.jar |
jarsigner
tool will tell you the JAR has been verified; otherwise, it will throw a SecurityException
indicating which files could not be verified.JARs can also be signed programmatically using the java.util.jar
and java.security
APIs. Alternatively, you can use tools such as Netscape Object Signing Tool.
You can also sign JARs programmatically using the java.util.jar
and java.security
APIs. (See Resources for details). Alternatively, you can use tools such as the Netscape Object Signing Tool.
If an application or applet is bundled into multiple JAR files, the class loader uses a simple linear search algorithm to search each element of the class path, which may entail the class loader downloading and opening many JAR files until the class or resource is found. If the class loader tries to find a nonexistent resource, all the JAR files within the application or applet will have to be downloaded. For large network applications and applets this could result in slow start up, sluggish response, and wasted network bandwidth.
Since JDK 1.3, the JAR file format has supported indexing to optimize the process of searching for classes in network applications, especially applets. The JarIndex mechanism collects the contents of all the JAR files defined in an applet or application and stores the information in an index file in the first JAR file. After the first JAR file is downloaded, the applet class loader will use the collected content information for efficient downloading of JAR files. This directory information is stored in a simple text file named INDEX.LIST in the META-INF directory of the root JAR file.
-i
option to the jar
command. Suppose we have a directory structure as depicted in the following diagram:Figure 2. JarIndex
You would use the following command to create an index file for JarIndex_Main.jar, JarIndex_test.jar, and JarIndex_test1.jar:
jar -i JarIndex_Main.jar JarIndex_test.jar SampleDir/JarIndex_test1.jar |
Listing 2. Example JarIndex INDEX.LIST file
|
The JAR format is much more than an archive format; it has many features for improving the efficiency, security, and organization of Java applications. Because these features are built into the core platform, including the compiler and classloader, developers can leverage the power of the JAR file format to simplify and improve their development and deployment processes.
петък, 27 юли 2007 г.
Creating a custom UI delegate for JTabbedPane
In my opinion one of the most underappreciated (and perhaps underused) features of Swing is the ability to create custom UI delegates for existing controls. It seems to me that most of the time new delegates are only created as part of developing a new complete look and feel, however I think they could be better leveraged to help add polish to existing applications.
For example, if you look at an application like Adobe Photoshop, in order to save space in their palettes, they use a small tab control. The same goes for most of the Microsoft Office products. They each contain customized tab controls that better integrate into the confinements of their respective user interfaces. Functionally, these behave like a standard tab controls, however the look and feel of these are different.
Over the years, I’ve seen many custom Swing controls implemented where the developers have re-implemented all that logic that already exists in an existing control with the only purpose of creating a version of that control that looks different. In fact, I know that I am guilty of doing that as well. Doesn’t it seem stupid to have to reimplement the logic for a button, a tab control, a checkbox or whatever control you are trying to create if your only goal is to change the way it looks?
Luckily for us Swing developers, there is a way just to address this exact problem.
I thought a good (and simple) example of how to implement a custom UI delegate would be to create an implementation for JTabbedPane that makes it look like the tabs used in the palletes of Adobe Photoshop:
Step 1: Create a new delegate class
If you’ve ever dug into the implementation of the different look and feels of Swing, you see that all the look and feels extend a basic look and feel implementation (in the javax.swing.plaf.basic package). These “basic” implementations (generally) break down the drawing of the respective controls into smaller units to make it easier to create a new delegates.Since we want to create a new delegate for JTabbedPane, our new class needs to extend the BasicTabbedPaneUI class:
import javax.swing.plaf.basic.BasicTabbedPaneUI;
public class PSTabbedPaneUI extends BasicTabbedPaneUI
{
}
Believe it or not, this is actually enough to start using this “custom” delegate in a real application. In the next step, we will create a test application that we can use to see the transformation as we implement our look and feel.Step 2: Create a small application to test our tabs
In order to test our new delegate, we need to create a small application that will use it. In order to get a good idea of how the delegate behaves, we will create a panel with three tabs in it. Tab 1 will contain a standard JPanel; Tab 2 will contain a JPanel with a black, 2 pixel border; and Tab 3 will contain a JButton. The reason we will do this, is that we can see the changes to the border of the content area of the tab, as well as the insets of the content area.
Here is the code that we will use for our sample application:
public class TestPSTabbedPaneUI
{
public static void main(String[] args)
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception exc)
{
// Do nothing...
}
JFrame vFrame = new JFrame();
vFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
vFrame.setSize(200, 200);
JTabbedPane vTab = new JTabbedPane();
vTab.setUI(new PSTabbedPaneUI());
vTab.add(\"One\", new JPanel());
JPanel vPanel2 = new JPanel();
vPanel2.setBorder(BorderFactory.createLineBorder(Color.BLACK,2));
vTab.add(\"Two\", vPanel2);
vTab.add(\"Three\", new JButton(\"three\"));
vFrame.getContentPane().add(vTab);
vFrame.setTitle(\"Tabs Example\");
vFrame.show();
}
}
If we would run this right now, we would see the following:As you can see, the application runs and is usable, but the tabs just look like standard (older) Windows style tabs. We can now begin with the fun stuff, actually changing the way the tabs are presented.
Step 3: Customize the way the tabs are drawn
In order to change the way the tabs are drawn, we need to override the paintTabBorder
method. If you look closely at the the tabs in Photoshop, you will see that in addition to having a border, there is a “beveled” look to the selected tab. It has a white line inside the left and top edge of the, and with a darker gray line inside of the right hand (angled) side. We will implement this beveled look in the paintTabBorder
method as well:
protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected)
{
g.setColor(Color.BLACK);
g.drawLine(x, y, x, y + h);
g.drawLine(x, y, x + w - (h / 2), y);
g.drawLine(x + w - (h / 2), y, x + w + (h / 2), y + h);
if (isSelected)
{
g.setColor(Color.WHITE);
g.drawLine(x + 1, y + 1, x + 1, y + h);
g.drawLine(x + 1, y + 1, x + w - (h / 2), y + 1);
g.setColor(shadow);
g.drawLine(x + w - (h / 2), y + 1, x + w + (h / 2)-1, y + h);
}
}
If we would run this right now, we would see the following:It’s still pretty ugly, but as you can see, by changing overriding one method, we already have made a drastic change to the way it looks.
Step 4: Customize the way the tabs are painted
If you look at the selected tab in the screenshots from step 3, you can see that you can see the edge of the border of the adjacent tabs. The next thing we will want to do is clean that up. In order to do that, we can extend the paintTabBackground
method. In this method, we will simply create a polygon which is the shape of the tab and fill it with the background color of the tab pane:
protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected)
{
Polygon shape = new Polygon();
shape.addPoint(x, y + h);
shape.addPoint(x, y);
shape.addPoint(x + w - (h / 2), y);
if (isSelected || (tabIndex == (rects.length - 1)))
{
shape.addPoint(x + w + (h / 2), y + h);
}
else
{
shape.addPoint(x + w, y + (h / 2));
shape.addPoint(x + w, y + h);
}
g.setColor(tabPane.getBackground());
g.fillPolygon(shape);
}
If we would run this right now, we would see the following:With that simple change, the tabs themselves look a lot cleaner and a lot more polished, however there is still alot we need to do finish things off.
Step 5: Supress the painting of the focus indicator
If you look at the Photoshop screenshot, there is no focus indicator for the tabs. Additionally, if you look at the screenshots from Step 4, you will notice that that the focus indicators are rectangular, while the buttons are not. In order to simulate the way the Photoshop tabs are implemented, we are going to supress the painting of the focus indicator. In order to do this, we just need to override the paintFocusIndicator
method and have it do nothing:
protected void paintFocusIndicator(Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex, Rectangle iconRect, Rectangle textRect, boolean isSelected)
{
// Do nothing
}
If we run our sample application now, we would see the following:
Without the focus indicator painted, it looks alot more like the original control we are copying.
Step 6: Change the insets of the tab bar
If look at the screenshot of the Photoshop tabs, you will notice that there is a 4 pixel gap between the left edge of the first tab (”Layers”) and the left hand side of the container. In our current version, the left hand side of the tab is directly agains the left edge of the container.
Additionally, if you look at our current version, you will see that the text for the tabs are inset a few pixels farther from the top edge of the tab than in the original Photoshop tab.In order to fix this, we need to override the installDefaults
method and change the default values for the insets. To fix problem number 1, we will need to modify the tabAreaInsets
field, and to fix problem number 2, we will need to modify the selectedTabPadInsets
field and the tabInsets
field:
protected void installDefaults()
{
super.installDefaults();
tabAreaInsets.left = 4;
selectedTabPadInsets = new Insets(0, 0, 0, 0);
tabInsets = selectedTabPadInsets;
}
If we run our sample application now, we would see the following:While we fixed the problem with the insets, the changes make our tabs look alot worse than before. In order to make them look better, we need a way to specify their size.
Step 7: Specify the size of the tabs
In order to specify the size of the tabs we need to override the calculateTabHeight
method and the calculateTabWidth
method. We can also use the
calculateTabHeight
method to enforce the fact that a tab will always be a height that is divisible by two. This will make sure that the angled line on the right hand side of the tabs always looks good (unlike the screenshots from the previous step).
protected int calculateTabHeight(int tabPlacement, int tabIndex, int fontHeight)
{
int vHeight = fontHeight;
if (vHeight % 2 > 0)
{
vHeight += 1;
}
return vHeight;
}
protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics)
{
return super.calculateTabWidth(tabPlacement, tabIndex, metrics) + metrics.getHeight();
}
If we run our sample application now, we would see the following:These changes now give our tabs the right proportions as compared to the real tabs in Photoshop. We can now turn our attention to the text of the tabs.
Step 8: Change the way the text is drawn
In Photoshop, the selected tab always has it’s text drawn in bold. Additionally, if you look at the text of all of the tabs in Photoshop, you will see they are all drawn at the same y location. In our tabs, the text for the selected tab is always drawn 2 pixels higher than the rest. In order to fix these problems, we will need to override a few methods.
First of all, we need to create the bold font to use to draw the selected text. We can create that font in theinstallDefaults
method where we specified the custom insets: protected void installDefaults()
{
super.installDefaults();
tabAreaInsets.left = 4;
selectedTabPadInsets = new Insets(0, 0, 0, 0);
tabInsets = selectedTabPadInsets;
boldFont = tabPane.getFont().deriveFont(Font.BOLD);
boldFontMetrics = tabPane.getFontMetrics(boldFont);
}
font
property of the tabPane to change so that you could update the cached bold font. For our simple example, we’ll overlook that small detail to simplify things.Next, in order to prevent the text of the selected tab to be drawn at a different y location than the unselected tabs, we need to override the getTabLabelShiftY
method:
protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected)
{
return 0;
}
paintText
method: protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected)
{
if (isSelected)
{
int vDifference = (int)(boldFontMetrics.getStringBounds(title,g).getWidth()) - textRect.width;
textRect.x -= (vDifference / 2);
super.paintText(g, tabPlacement, boldFont, boldFontMetrics, tabIndex, title, textRect, isSelected);
}
else
{
super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected);
}
}
If we run our sample application now, we would see the following:Step 9: Paint the background behind the tabs
If you look at the background behind (and to the right) of the tabs in Photoshop, it is painted a little bit darker than the color of the tabs. In order to implement this, we need to override the paintTabArea
method.
Before we do that however, we need to decide what color to paint the background. In order to make this delegate work fairly well with any look and feel, we will simply create a darker version of the background color by calling the darker()<> method on the background color. We can add the creation of this color to the
installDefaults
method like we’ve done before:
protected void installDefaults()
{
super.installDefaults();
tabAreaInsets.left = 4;
selectedTabPadInsets = new Insets(0, 0, 0, 0);
tabInsets = selectedTabPadInsets;
Color background = tabPane.getBackground();
fillColor = background.darker();
boldFont = tabPane.getFont().deriveFont(Font.BOLD);
boldFontMetrics = tabPane.getFontMetrics(boldFont);
}
Now that we have that out of the way, we can implement the paintTabArea
method: protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex)
{
int tw = tabPane.getBounds().width;
g.setColor(fillColor);
g.fillRect(0, 0, tw, rects[0].height + 3);
super.paintTabArea(g, tabPlacement, selectedIndex);
}
If we run our sample application now, we would see the following:The color is a little darker than in the original, however by implementing it this way, the delegate should be reusable between any look and feel (and any background color). You’ll also notice that we have the same issue with the font. The font does match up exactly, but by using the default font for the look and feel, we make the delegate more portable.
Step 10: Change the way the top border of the content area is drawn
If you at the screenshot from the previous step where tab “One” is selected, you will notice that there are a few problems with how the top line of the content area is painted. First of all, the Photoshop tabs have a black line there as opposed to a while line. Secondly, there is a bevel effect in the real version, and finally in our (current) version, the lines don’t even match up to the border of the tabs (on the right hand side of the tab where the angle comes down).
In order to fix this, we will need to override the paintContentBorderTopEdge
method:
protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h)
{
Rectangle selectedRect = selectedIndex < width =" selectedRect.width">
If we run our sample application now, we would see the following:With those changes, we are now done with the tab area itself. Now, we just need to clean up the borders (actually remove them) of the content area.
Step 11: Removing the borders in the content area
In order to remove the borders of the content area, we just need to override the methods paintContentBorderRightEdge
, paintContentBorderLeftEdge
and paintContentBorderBottomEdge
and have them do nothing:
protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h)
{
// Do nothing
}
protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h)
{
// Do nothing
}
protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h)
{
// Do nothing
}
If we run our sample application now, we would see the following:If you look at the screenshot where “One” is selected, you might think we are done with our delegate. However, if you look at the screenshot where tab “Two” is selected, you will notice that the content is still inset a little bit from the edges. In the orignal Photoshop tab, there is no inset, so we still need to remove that before we can be finished.
Step 12: Removing the content area insets
Implementing this turns out to be quite simple as well. All we need to do is override thegetContentBorderInsets
method: protected Insets getContentBorderInsets(int tabPlacement)
{
return new Insets(2, 0, 0, 0);
}
If we run our sample application now, we would see the following:
If you look at the screenshot where the tab “Two” is selected, you can now see that content area extends to the borders exactly like the Photoshop example.
If you want to play with the example yourself, you can download the source code for the delegate here, and you can download the source code for the test application here.
четвъртък, 19 юли 2007 г.
External JavaScript Character Set Encoding for Firefox and Internet Explorer
I have found that for me to force IE to display non-English characters from an external JavaScript file, where a dynamic element is added to the page on the fly, the best way to handle this is via the "native2ascii" application from JDK.
native2ascii somefile.js
JavaScript: Replace Text Found in a Node and its Subnodes of the DOM Tree
function engrish(n)
{
if(n.nodeType == document.TEXT_NODE)
{
n.nodeValue = n.nodeValue.replace(/l/g, 'r').replace(/L/g, 'R');
}
else if(n.hasChildNodes())
{
for(var i=0; i < n.childnodes.length; i++)
engrish(n.childNodes[i]);
}
}
}
Add and Remove HTML elements dynamically with Javascript
function addElement()
{
var ni = document.getElementById('myDiv');
var numi = document.getElementById('theValue');
var num = (document.getElementById('theValue').value -1)+ 2;
numi.value = num;
var newdiv = document.createElement('div');
var divIdName = 'my'+num+'Div';
newdiv.setAttribute('id',divIdName);
newdiv.innerHTML = "Some contents";
ni.appendChild(newdiv);
// For IE, set any attributes directly;
// do not use the setAttribute method().
// E.g. use newdiv.style.zIndex = "1000" instead of
// newdiv.setAttribute('style','z-index: 1000;');
}
function removeElement(divNum)
{
var d = document.getElementById('myDiv');
var olddiv = document.getElementById(divNum);
d.removeChild(olddiv);
}
събота, 14 юли 2007 г.
вторник, 3 юли 2007 г.
Replacing a Hard Drive on Dell Inspiron
http://support.dell.com/support/edocs/systems/ins9400/en/sm/hddrive.htm#wp1123687