Posts in the 'Programming' category

Apr
21
2008

Creating Good Looking 16×16 Icons



Posted in Programming

If you’re creating an icon for an application or a website, getting it to look good at 16×16 can be difficult. I spent a few hours getting it right yesterday, so here’s a guide to get you started.

Good Looking 16×16 Icons

Mar
26
2008

Priority Queue in C#



Posted in Programming

A priority queue is like a standard queue, but instead of dequeuing items on a first-in-first-out basis, items are instead served by priority. There are lots of implementations of a priority queue, but none I could find which let the user re-order items. The following class functions just like a regular queue, but can also change the order of items in the queue by their index.

The queue is designed to be used with a ListView set to details mode, but could be adapted for use elsewhere. Using it with a ListView makes sense since the first item in the queue (the next to be executed) is always at index 0, and the indexing for a ListView also starts at 0.

Read more »

Mar
23
2008

Retrieving Shell Icons in C#



Posted in Programming

Ever needed to retrieve the shell icon for a particular file type in C#? This class will retrieve the Icon associated with a file from just the extension.

using System;
using System.Runtime.InteropServices;
using System.Drawing;
 
namespace Lime49.Utils {
    /// <summary>
    /// Retrievs shell info associated with a file or filetype
    /// </summary>
    /// <summary>
    /// Get a 32x32 or 16x16 System.Drawing.Icon depending on which function you call
    /// either GetSmallIcon(string fileName) or GetLargeIcon(string fileName)
    /// </summary>
    public class ShellIcon {
        [StructLayout(LayoutKind.Sequential)]
        public struct SHFILEINFO {
            public IntPtr hIcon;
            public IntPtr iIcon;
            public uint dwAttributes;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
        };
        class Win32 {
            public const uint SHGFI_ICON = 0x100;
            public const uint SHGFI_LARGEICON = 0x0; // Large icon
            public const uint SHGFI_SMALLICON = 0x1; // Small icon
            public const uint USEFILEATTRIBUTES = 0x000000010; // when the full path isn't available
            [DllImport("shell32.dll")]
            public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
            [DllImport("User32.dll")]
            public static extern int DestroyIcon(IntPtr hIcon);
        }
	...

Read more »

Feb
15
2008

Java: Word Wrap for JLabels



Posted in Programming

Why couldn't Sun have made JLabels automatically wrap when they're too wide to fit the container they're in? I'd been trying to get a custom component to automatically wrap for hours, then someone suggested a JTextPane in IRC. You can style the pane to look like a JLabel, and it automatically wraps.

JTextPane txtMyTextPane= new JTextPane();
            txtMyTextPane.setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas aliquam sem et nunc vulputate aliquet. Duis sollicitudin. Vestibulum sit amet lacus a risus egestas nonummy. Donec eu odio id felis auctor lobortis. Cras id nisl vitae pede lacinia elementum. Suspendisse convallis leo. Donec elit. Quisque id mi tincidunt quam tristique posuere.");
            txtMyTextPane.setBackground(null);
            txtMyTextPane.setEditable(false);
            txtMyTextPane.setBorder(null);
Feb
8
2008

Java: Close a JFrame with Escape



Posted in Programming

This will close a JFrame when the escape key is pressed. The actionPerformed method can do be used to call another method or to close the frame which called it.

KeyStroke escapeKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
Action escapeAction = new AbstractAction() {
    // close the frame when the user presses escape
    public void actionPerformed(ActionEvent e) {
        myFrame.dispose();
    }
}; 
myFrame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escapeKeyStroke, "ESCAPE");
myFrame.getRootPane().getActionMap().put("ESCAPE", escapeAction);
Jan
24
2008

Idiots Guide to Installing PHP



Posted in Programming and Technology

If you have hosting with Dreamhost or any other host which gives you a shell account, you can install your own custom version of PHP. I needed to compile PHP with GMP support for the OpenID login plugin for WordPress, so I spent the whole day tweaking trying to get everything working. There's a page on Dreamhost's Wiki which has a script, but it still took me hours to get right. I've written a quick guide to help avoid the mistakes which slowed me down.

  1. The first thing you need to do is download Putty and set it up to connect to your host.
  2. We're going to create a few shell scripts to install PHP and all the other packages it requires. It's probably easiest to make your edits in notepad or another text editor, then copy and paste them into Putty by right-clicking. If you just create the files then upload them, there tend to be problems with line breaks and the script doesn't work.
  3. Start by downloading the preparation script and the installation script. Open them with a text edtitor and change the line export DOMAIN="yourdomainhere.com" to match the domain you're installing the CGI script on. This should be the directory the domain is served from. Eg: If your site serves files from /home/someone/xyz.com, use xyz.com. The version information may need updating, because I won't be updating this script.
  4. The first script we need to set up will download the different packages and extract them. Once you're done editing, hit CTRL+A in your text editor, then copy everything to your clipboard. Create a new file by typing nano php_prep.sh at the command prompt.
  5. Paste the contents of your clipboard into the new file by right clicking in Putty, then hit CTRL+O to save the file, then CTRL+X to exit nano.
  6. In *nix you need to make files excutable before you can run them. Do this by typing chmod +x php_prep.sh
  7. Now we need to set up the script which does the installing. Create a new file by typing nano php_inst.sh at the prompt, then copy and paste the contents of your edited php_inst.sh file by right clicking the terminal. Hit CTRL+O, Return, then CTRL+X to save and exit.
  8. Make the file executable by typing chmod +x php_inst.sh
  9. Now that everything's set up, we can run the first script by typing ./php_prep.sh at the prompt. It might take a while but if there are no errors you should eventually see "Done downloading and unpacking prerequisites".
  10. Run the installation script using ./php_inst.sh . This might take a while to complete, so start solitaire or something.
  11. When everything's finished, you should see "INSTALL COMPLETE!" and have a shiny new custom version of PHP installed.
  12. If you don't already have one, create a .htaccess file at the root of your domain. You can do this by typing nano .htaccess. Add the following lines:
    Options +ExecCGI
    AddHandler php-cgi .php
    Action php-cgi /cgi-bin/php.cgi
  13. That should be it. If there were no errors, you can test your installation by viewing a PHP file on your site. Hopefully you'll either see no change, but it's possible you'll see a load of errors.

If you have problems installing, the Dreamhost forums might be a good place to ask for help.

Jan
10
2008

Java Methods for TreeNodes



Posted in Programming

Two pretty useful Java methods. They're both related to JTrees, but should have been included as built in methods really.

The first returns a treepath given an object. Once you have a JTree, you may need to get the path to the node that contains that object (to scroll the JTree to that object for example). It's a recursive function so it doesn't matter how many levels your JTree contains.

    private TreePath getPathToNode(DefaultMutableTreeNode node, Object obj) {
	System.out.println("Looking for "+obj.toString()+" in "+node.toString());
        if(node.toString().equals(obj.toString())) {
            return new TreePath(node.getPath());
        } else {
            for(Enumeration theChildren = node.children(); theChildren.hasMoreElements();) {
                DefaultMutableTreeNode thisNode = (DefaultMutableTreeNode)theChildren.nextElement();
                if(thisNode.toString().equals(obj.toString())) {
                    System.out.println("Found node at "+new TreePath(thisNode.getPath()));
                    return new TreePath(thisNode.getPath());
                } else if(thisNode.getChildCount()>0) {
                    for(Enumeration grandChildren = thisNode.children(); grandChildren.hasMoreElements();) {
                        DefaultMutableTreeNode grandChild = (DefaultMutableTreeNode)grandChildren.nextElement();
                        TreePath n = getPathToNode(grandChild, obj);
                        if(n != null) {
                            return n; // if the call returns anything but null, we've found the node
                        }
                    }
                }
            }
            System.out.println("Node not found");
            return null;
        }
    }

The second returns a DefaultMutableTreeNode given an object. It recursively searches the JTree until it finds the object matching the one you pass to it, then returns the node containing that object.

    private DefaultMutableTreeNode getNodeFromName(DefaultMutableTreeNode node, Object obj) {
        // Used to scroll the JTree to the current account
        for(Enumeration theChildren = node.children(); theChildren.hasMoreElements();) {
            DefaultMutableTreeNode thisNode = (DefaultMutableTreeNode)theChildren.nextElement();
            if(thisNode.toString().equals(obj.toString())) {
                return thisNode;
            } else {
                if(thisNode.getChildCount()>0) {
                    for(Enumeration grandChildren = thisNode.children(); grandChildren.hasMoreElements();) {
                        DefaultMutableTreeNode grandChild = (DefaultMutableTreeNode)grandChildren.nextElement();
                        DefaultMutableTreeNode n = getNodeFromName(grandChild, obj);
                        if(n != null) {
                            return n; // if the call returns anything but null, we've found the node
                        }
                    }
                }
            }
        }
        System.out.println("Node not found");
        return null;
    }
Dec
20
2007

in_array() and implode() for Java



Posted in Programming and Technology

I'm still getting to grips with Java, but there a few functions I miss coming from PHP. in_array lacks a Java equivalent, as does the implode function. Here are the equvalent methods in Java:

implode()

static String implode(String[] ary, String delim) {
    String out = "";
    for(int i=0; i<ary.length; i++) {
        if(i!=0) { out += delim; }
        out += ary[i];
    }
    return out;
}

in_array()

private boolean in_array(DefaultListModel haystack, String needle) {
    for(int i=0;i<haystack.size();i++) {
        if(haystack.get(i).toString().equals(needle)) {
            return true;
        }
    }
    return false;
}
Dec
9
2007

Limit and Offset clauses in MSSQL



Posted in Programming and Technology

Until SQL server 2008's released, there’s no easy way to page reults or only show the first n results. I searched around for a while until I found this on MSDN.

SELECT TOP limitnumber
    FROM (
        SELECT TOP (limitnumber/ offset) * limitnumber) * 
        FROM tablename 
            AS T1 
            WHERE clauses 
            ORDER BY sortfield DESC) 
        AS T2 
        ORDER BY sortfield ASC;

The LIMIT and OFFSET values are the same as in PostgreSQL or MySQL. limitnumber is the number to show per page, and offset is the starting row.

MSDN Article

Nov
14
2007

Inserting Multiple Rows with MSSQL



Posted in Programming and Technology

I've been working on adding support for Microsoft SQL Server to iZeit, and there are a few things I've noticed. Firstly, whereas you can addin multiple rows in MySQL or Postgres by using

INSERT INTO tablename (field1,field2,field3) VALUES (r1c1, r1c2, r1c3), (r2c1,r2c2,r2c3)

MSSQL fails and throws an error. Instead, you have to use UNION ALL, which I always thought was more resource intensive.

INSERT INTO tablename (field1,field2,field3) SELECT (r1c1, r1c2, r1c3) UNION ALL SELECT (r2c1,r2c2,r2c3)

The second major annoyance is that MSSQL doesn't like ORDER BY clauses with text fields. Understandably you can't sort a field containing an image, but why can't it sort a text field alphabetically? One thing I still haven't found a workaround for is the LIMIT and OFFSET clauses, which MSSQL doesn't support.

Jun
6
2007

LOLCode - Programming for AOL Kiddies



LOLCode is an "awesome new programming language" for MySpace kids everywhere. It uses familiar vocabulary and with a fast growing list of functions, could soon over-take more traditional languages like PHP.

HAI
CAN HAS STDIO?
I HAS A VAR
IM IN YR LOOP
     UP VAR!!1
     VISIBLE VAR
     IZ VAR BIGGER THAN 10? KTHXBYE
IM OUTTA YR LOOP
KTHXBYE

Read more at LOLCode.com

Feb
1
2007

Dynamic Form Submit



I've just released iZeit v1.7, a calendar written in PHP. One of the things I added to this version was JavaScript forms created on the fly to replace image links. There was a problem recently with Google Web Accelerator, which preloaded all links on the current page so they'd load faster when they were needed. That might sound like a good idea, until you get a page full of delete links that use variables passed via the GET method. Creating a form on the fly and submitting it using POST looks nicer, is alot more secure and isn' subject to Google's interfering web accelerator. Instead of using the href of an anchor, you use an onclick event in the anchor instead.

‹a title="Delete Category" onclick="var f = document.createElement('form');
f.style.display = 'none'; this.parentNode.appendChild(f);
var h = document.createElement('input'); h.type = 'hidden'; h.name = 'act'; h.value = 'admin'; f.appendChild(h);
var h2 = document.createElement('input'); h2.type = 'hidden'; h2.name = 'setadmin'; h2.value = 'delcat'; f.appendChild(h2);
f.method = 'POST';
f.action = 'index.php';
f.submit();
return false;"›
‹img border="0" src="delete.gif" alt="Delete category" /›‹/a›
Jan
28
2007

Things you didn’t know about PHP



Posted in Programming and Technology

I've been developing in PHP for a while now, mostly iZeit, my PHP calendar script, but also the odd smaller script and I've picked up a few things along the way.

Quotes vs. Double Quotes

Anything in double quotes is parsed by PHP and variables are replaced. So if you’re concatenating things, use single quotes instead:

$name = 'Bob';
echo 'Name is '.$name;   // Name is Bob
echo "Name is $name";   // Name is Bob
echo 'Name is $name';   // Name is $name
echo "Name is ".$name;   /* Name is Bob, but wastes processing
time because the non dynamic part of the statement is parsed for variables. */

Check whether a variable's set first

There are times when if you try to use a variable that isn't set, PHP will throw an error at you.

$param = isset($_GET['param']) ? $_GET['param'] : NULL;

Using shorttags

I have no idea why they even added shorttags. Using <?php ?> instead of <? ?> will make your scripts run on alot more servers which don't have short tags enabled in php.ini.

Jan
10
2007

HOW TO: Clickable Smiley Panel



Posted in Internet and Programming

If you spend alot of time on forums, there’s an easy way to make a panel of clickable images which copy the location of the image to your clipboard so you can paste it onto a forum. It’s good for emoticons or anything else which takes a while to type out. You can arrange the images any way you want, then add the following piece of Javascript to the head:

<script type="text/javascript">
function toclip(iurl) {
	if(document.getElementById('forum').checked) {
		var imgtext = '[img]'+iurl+'[/img]';
	} else {
		var imgtext = '<img src="'+iurl+'" alt="" />';
	}
	if (window.clipboardData) {
		window.clipboardData.setData("Text", imgtext); //IE
	} else if (window.netscape) {
		netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
		var clip = Components.classes['@mozilla.org/widget/clipboard1'].
createInstance(Components.interfaces.nsIClipboard);
		if (!clip) return;
		var trans = Components.classes['@mozilla.org/widget/transferable1'].
createInstance(Components.interfaces.nsITransferable);
		if (!trans) return;
		trans.addDataFlavor('text/unicode');
		var str = new Object();
		var len = new Object();
		var str = Components.classes["@mozilla.org/supports-string1"].
createInstance(Components.interfaces.nsISupportsString);
		var copytext=imgtext;
		str.data=copytext;
		trans.setTransferData("text/unicode",str,copytext.length*2);
		var clipid=Components.interfaces.nsIClipboard;
		if (!clip) return false;
		clip.setData(trans,null,clipid.kGlobalClipboard);
		}
//   alert("Following info was copied to your clipboard:\n\n" + iurl);
	return false;
}
</script>

Then to copy the text to the clipboard when the icon is clicked, call the function with Javascript:

<a onclick="toclip('http://url//of/image.gif');"
href="#"><img src="image.gif" alt="Woot" /></a>

The function works fine with IE, but to get it working in Firefox, you need to allow Firefox clipboard access. Type about:config into the address bar, then 'signed' as the filter, and set the value to true.


2 Pages«12