.NET Dock Panel

13
Jan/10
0

Apparently .NET does not come with any dock widget, like the ones used for the Toolbox and Properties window in Visual Studio. However, there is a freely available one on sourceforge called DockPanel Suite. Unfortunately, it seems to lack any sort of documentation!

This little code snippet below should be enough to get you started though. Just make sure you your form’s IsMdiContainer property to True first.

public Form1() {
    InitializeComponent();

    glControl.Load += new System.EventHandler(glControl_Load);
    glControl.Paint += new System.Windows.Forms.PaintEventHandler(glControl_Paint);
    glControl.Dock = DockStyle.Fill;

    var dockPanel = new DockPanel();
    dockPanel.Dock = DockStyle.Fill;
    Controls.Add(dockPanel);
    dockPanel.BringToFront();

    var mainDock = new DockContent();
    mainDock.ShowHint = DockState.Document;
    mainDock.TabText = "untitled1";
    mainDock.Controls.Add(glControl);
    mainDock.Show(dockPanel);

    var propGrid = new PropertyGrid();
    propGrid.Dock = DockStyle.Fill;

    var propertyDock = new DockContent();
    propertyDock.Controls.Add(propGrid);
    propertyDock.ShowHint = DockState.DockRight;
    propertyDock.TabText = "Properties";
    propertyDock.Show(dockPanel);
}

C# Blocking Queue

20
Dec/09
0

If you’re writing a threaded application in C# and you need to wait until a resource becomes available, you can use this class. Very handy for producer/consumer scenarios.

public class BlockingQueue<T>
{
    Queue<T> que = new Queue<T>();
    Semaphore sem = new Semaphore(0, Int32.MaxValue);

    public void Enqueue(T item)
    {
        lock (que)
        {
            que.Enqueue(item);
        }

        sem.Release();
    }

    public T Dequeue()
    {
        sem.WaitOne();

        lock (que)
        {
            return que.Dequeue();
        }
    }
}

Django, Flatpages, Markdown, and Syntax Highlighting

11
Oct/09
0

For what should have been an easy task, this turned out to be extraordinarily difficult.

I assume you have Django already installed. If not, the tutorials on djangoproject.com aren’t too terrible, provided you’re not on a shared server (that’s another story!). I’m using Flatpages, but you can use whatever you want to follow along with this tutorial.

1. Install Markdown and Pygments for Python if you haven’t already. If you’re on Ubuntu, you can `sudo apt-get install python-markdown` or `easy_install Markdown` and `sudo apt-get install python-pygments`.

2. Go into your Django app and `mkdir templatetags`. This should be at the same level as `manage.py`, `settings.py` and `urls.py`. Then `cd` into that directory, and `touch __init__.py` (so that it becomes a module) and then add another file called something like `tags.py` (don’t name it “markdown.py” — that’ll bite you later). Paste this code in there:

from django import template
from django.template.defaultfilters import stringfilter

from django.conf import settings

register = template.Library()

@register.filter(name='markdown')
@stringfilter
def markdown(value, arg=''):
    """
    Filter to create HTML out of Markdown, using custom extensions.

    The diffrence between this filter and the django-internal markdown
    filter (located in ``django/contrib/markup/templatetags/markup.py``)
    is that this filter enables extensions to be load.

    Usage::

        {{ object.text|markdown }}
        {{ object.text|markdown:"save" }}
        {{ object.text|markdown:"codehilite" }}
        {{ object.text|markdown:"save,codehilite" }}

    This code is taken from
    http://www.freewisdom.org/projects/python-markdown/Django
    """

    try:
        import markdown
    except ImportError:
        if settings.DEBUG:
            raise (template.TemplateSyntaxError,
                   "Error in {% markdown %} filter: "
                   + "The markdown library isn't installed.")
        else :
            from django.utils.html import escape, linebreaks
            return linebreaks(escape(value))
    else:
        extensions=arg.split(",")
        if len(extensions) > 0 and extensions[0] == "safe" :
            extensions = extensions[1:]
            safe_mode = True
        else :
            safe_mode = False
        return markdown.markdown(value, extensions, safe_mode=safe_mode)

Yes, I’m leaving the link in there; I didn’t write that code.

3. Go into `settings.py` and add your app to the `INSTALLED_APPS`. You actually have to `import` your own app too; this baffled me for about an hour. My app is called `tech_eval` so my `INSTALLED_APPS` looks like this:

import tech_eval # you can put this line at the top of settings.py if you want

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    'django.contrib.flatpages',
    'tech_eval',
)

4. Like I said, I’m using Flatpages, so my template looks like this (I saved it to djangoproject/app/templates/flatpages/default.html).

{% load tags %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <title>{{ flatpage.title }}</title>
    <link rel="stylesheet" type="text/css" href="/tech_eval/media/css/code_style.css" />
</head>
<body>
    <h1>{{ flatpage.title }}</h1>
    {{ flatpage.content|markdown:"codehilite"|safe}}
</body>
</html>

Notice how we filter the content with markdown, make sure the codehilite extension is used, and flag it as `safe` afterwords (otherwise Django will automatically character-encode everything).

5. Hopefully this is already working for you at this point, but you probably want to add some color to your code. You can generate the appropriate css file with this:

pygmentize -f html -S default -a .codehilite >> code_style.css

Some different styles you can use (at least on my system) are:

['manni', 'colorful', 'murphy', 'autumn', 'bw', 'pastie', 'native', 'perldoc', 'borland', 'trac', 'default', 'fruity', 'emacs', 'friendly']

(stolen from here).

Or just copy and paste this CSS file if you’re lazy:

.codehilite .c { color: #408080; font-style: italic } /* Comment */
.codehilite .err { border: 1px solid #FF0000 } /* Error */
.codehilite .k { color: #008000; font-weight: bold } /* Keyword */
.codehilite .o { color: #666666 } /* Operator */
.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
.codehilite .gd { color: #A00000 } /* Generic.Deleted */
.codehilite .ge { font-style: italic } /* Generic.Emph */
.codehilite .gr { color: #FF0000 } /* Generic.Error */
.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.codehilite .gi { color: #00A000 } /* Generic.Inserted */
.codehilite .go { color: #808080 } /* Generic.Output */
.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.codehilite .gs { font-weight: bold } /* Generic.Strong */
.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.codehilite .gt { color: #0040D0 } /* Generic.Traceback */
.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.codehilite .kp { color: #008000 } /* Keyword.Pseudo */
.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.codehilite .kt { color: #B00040 } /* Keyword.Type */
.codehilite .m { color: #666666 } /* Literal.Number */
.codehilite .s { color: #BA2121 } /* Literal.String */
.codehilite .na { color: #7D9029 } /* Name.Attribute */
.codehilite .nb { color: #008000 } /* Name.Builtin */
.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.codehilite .no { color: #880000 } /* Name.Constant */
.codehilite .nd { color: #AA22FF } /* Name.Decorator */
.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.codehilite .nf { color: #0000FF } /* Name.Function */
.codehilite .nl { color: #A0A000 } /* Name.Label */
.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
.codehilite .nv { color: #19177C } /* Name.Variable */
.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
.codehilite .mf { color: #666666 } /* Literal.Number.Float */
.codehilite .mh { color: #666666 } /* Literal.Number.Hex */
.codehilite .mi { color: #666666 } /* Literal.Number.Integer */
.codehilite .mo { color: #666666 } /* Literal.Number.Oct */
.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
.codehilite .sc { color: #BA2121 } /* Literal.String.Char */
.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.codehilite .sx { color: #008000 } /* Literal.String.Other */
.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
.codehilite .ss { color: #19177C } /* Literal.String.Symbol */
.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
.codehilite .vc { color: #19177C } /* Name.Variable.Class */
.codehilite .vg { color: #19177C } /* Name.Variable.Global */
.codehilite .vi { color: #19177C } /* Name.Variable.Instance */
.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */
.codehilitetable { border: 1px solid #666; width: 100%; background-color: #666; }
.codehilitetable .linenos { background-color: #666; padding: 0 5px; width: 20px; }
.codehilitetable .code { padding: 0 15px; background-color: #fff; }

And that should pretty much be it. Let me know if I missed anything or this was too difficult to follow along.

Qt + OpenGL Code Example

9
Aug/09
0

I wanted to develop a game using OpenGL but I was having trouble deciding on a windowing library. Somebody suggested I try Qt, so I decided to give it another shot. I heard it was good, but the editor it came with was so foreign and unintuitive. Unfortunately, this overshadowed what a beautiful library Qt really is! It takes a little getting used to, but it really is well designed.

Filed under: C++

array_map_recursive

7
Jul/09
0

Not much needs to be said here.

function array_map_recursive($callback, $arr) {
    $ret = array();
    foreach($arr as $key => $val) {
        if(is_array($val)) $ret[$key] = array_map_recursive($callback, $val);
        else $ret[$key] = $callback($val);
    }
    return $ret;
}

I wrote this so that I could do this…

$filters = array('htmlspecialchars', 'nl2br');
foreach($filters as $filter) $view_vars = array_map_recursive($filter, $view_vars);

Which just sanitizes my variables before I print them.

Filed under: PHP

All I want is a drag-and-drop CD burner

5
Jul/09
0

I know I’ve mostly been posting code snippets here, but I originally started this site to post more in-depth tutorials. This isn’t going to be one of those. I’m taking a spin and would like to say a few words on the design of good software — the second half of this site that’s been neglected.

My brother’s girlfriend asked me to burn some files for her using her laptop the other day, so I tried. I didn’t think it would be so difficult.

So I popped in the blank disc, and iTunes came up, exclaiming that it could burn stuff for me. Fine, I’ll try that. It told me I had to create a new playlist (Why? I’m just going to delete it in 5 seconds). So I did. And then I tried to drag and drop my videos onto the playlist. Nothing. Okay. Let’s dig through the menus: “Add to playlist”? No. “Import files”? No. It looks to me like I have to add the files to my library, then search for those files that I just added, figure out how to add them to my newly created playlist, burn them, and then delete the playlist I didn’t want in the first place. Brilliant. Except I couldn’t figure that out, and I still haven’t the faintest idea how to use iTunes. Call me idiot, iTune-lovers, but software really shouldn’t take more than about 3 minutes to figure out how to do what you want with it.

Next I tried ImgBurn, something a friend recommended to me, which was indeed great for burning images, as the name suggests, but pretty horrid at burning a list of files. Fail.

I eventually just went into “My Computer” and dragged some files on it. Windows told me I had to format the CD (it was rewriteable) first. Fine. That took an extraordinarily long time, and then finally when it started burning it told me it would be finished in 0 seconds, but it literally took between thirty minutes and an hour. I know her drive isn’t that slow, it’s a new computer.

CDBurnerXP has worked great in the past for me, but apparently it’s a failure on Windows 7. The “used space” bar was just plain wrong, and when I tried telling it that it was an idiot, it threw a fit and crashed.

Nero was good, back in the day, until they figured out they were getting popular and thought they could get away with adding whatever crapware they wanted. Now I just refuse to support their bullshit.

All I wanted to do was to drag-and-drop some files onto a program window, list them for me, and tell me how much space I’ve got left. Click burn, and that’s it. Don’t touch my files, don’t convert them, don’t move, copy, sort, cache or archive them. Don’t install useless crap on my computer, and don’t have me six thousand features I don’t need.

Give me what I want. Make it big, bold, obvious, easy to find. And make it do what it’s supposed to do when I click it. No more, no less. Is that so hard? Why can’t people develop nice, clean, simple, intuitive UIs? We’re not asking you to invent anything new, just take what’s already been done, and works, and use that. There’s frameworks for it. Use them!

jQuery Select Table Column or Row

5
Jul/09
0

Table rows are pretty easy to work as all the td elements are contained within one tr, but how would you grab all the tds in a single column? Why, by using these selectors of course!

$.fn.row = function(i) {
    return $('tr:nth-child('+(i+1)+') td', this);
}
$.fn.column = function(i) {
    return $('tr td:nth-child('+(i+1)+')', this);
}

// example - this will make the first column of every table red
$(document).ready(function() {
    $('table').column(0).css('background-color','red');
});

I like my selectors zero-based, but you can get rid of the +1 if you don’t like it.

Filed under: JavaScript

SQL Injection Safe Queries Redux

30
Jun/09
2
function mysql_safe_string($value) {
    if(is_numeric($value))      return $value;
    elseif(empty($value))       return 'NULL';
    elseif(is_string($value))   return '\''.mysql_real_escape_string($value).'\'';
    elseif(is_array($value))    return implode(',',array_map('mysql_safe_string',$value));
}

function mysql_safe_query($format) {
    $args = array_slice(func_get_args(),1);
    $args = array_map('mysql_safe_string',$args);
    $query = vsprintf($format,$args);
    $result = mysql_query($query);
    if($result === false) echo '<div class="mysql-error"><strong>Error: </strong>',mysql_error(),'<br/><strong>Query: </strong>',$query,'</div>';
    return $result;
}

// example
$result = mysql_safe_query('SELECT * FROM users WHERE username=%s', $username);

Just use mysql_safe_query in place of mysql_query and you should be safe from SQL injection attacks. Use %s in place of any variables, and append them as arguments. Don’t quote your strings, it’ll be done for you automatically. Arrays will be flattened for you automatically and concatenated with commas. You can delete the error-echoing line if you want, but I find it useful for development.

Filed under: PHP

Facebook PHP API: Get the names of all your friends

30
Jun/09
0

If you didn’t already know, Facebook has an API that exposes quite a darn bit information. You can easily query this data using their API, but each request takes a fair bit of time. Typically, to get the names of all your friends, first you have to grab a list of the user ids of all your friends, and then query each and every single one to get their names. For me, that’s about 300 cross-server requests, which will almost certainly cause my server to time out, and probably force Facebook to reject me. Fortunately, Facebook has also created their own MySQL-like language, FQL (I pronounce it feequel), which lets you do some of these “complicated” queries in a single call. Here’s a simple example I wrote:

<?php
require_once 'facebook-platform/php/facebook.php';

$appapikey = 'yourapikeyhere';
$appsecret = 'yoursecretkey';
$facebook = new Facebook($appapikey, $appsecret);
$user_id = $facebook->require_login();

$result = fql_query('SELECT name FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=%s)', $user_id);
pr($result);


function fql_query($query) {
    global $facebook;
    $args = array_slice(func_get_args(), 1);
    return $facebook->api_client->fql_query(vsprintf($query, $args));
}

function pr($arr) {
    echo '<pre>';
    print_r($arr);
    echo '</pre>';
}

You’ll notice I’ve included two of my favorite wrapper functions. You can unroll them if you want. Anyway, just thought I’d share :) I prefer writing FQL than trying to remember all their API calls anyway.

Oh… and just FYI, this prints out something like this:

Array
(
    [0] => Array
        (
            [name] => Mark Zuckerberg
        )

    [1] => Array
        (
            [name] => Tom Riddle
        )

I hate it when people leave it a mystery what exactly their example is doing!

Filed under: PHP

Get Domain & Subdomain from URL

23
Jun/09
2
preg_match('/^(?:www\.)?(?:(.+)\.)?(.+\..+)$/i', $_SERVER['HTTP_HOST'], $matches);

define('PROTOCOL', strtolower(substr($_SERVER['SERVER_PROTOCOL'],0,strpos($_SERVER['SERVER_PROTOCOL'],'/'))).'://');
define('SUBDOMAIN', $matches[1]);
define('DOMAIN', $matches[2]);
define('HERE', $_SERVER['REQUEST_URI']);

If you’re at http://www.sub.domain.com/page, then:

PROTOCOL = http://
SUBDOMAIN = sub
DOMAIN = domain.com
HERE = /page

Filed under: PHP