Gimp and .eps Files

I use Gimp on all systems and I've some Encapsulated PostScript (.eps) files on Windows that I need to open and edit. In order to Gimp on Windows open .eps files, it requires Ghostscript to be in your system.

Here's how to do it:
  1. Download and install Gimp;
  2. Download and install Ghostscript
  3. Setup the environment variable GS_PROG to the Ghostscript executable file, like C:\Program Files\gs\gs8.64\bin\gswin32.exe.
Now Gimp should be abble to open EPS files.

./M6

JFace TreeView with Manual Expand of TreeItems

I have a FilteredTree with check items and I was trying to expand the tree whenever the user checks an item on it. By default, the tree does only expand a TreeItem when the user clicks on the + icon and retracts when the user clicks on the - icon.
Since this tree has check items, I wanted the tree to expand when the user clicks on the check box.

This proved to be a lot harder than I expected, partially because I was using the wrong object, partially because it is lazy, and partially because it was hard to find an answer for what I was doing wrong.
So, I'm posting here how to manually expand a TreeView, which is part of a FilteredTree.

To begin with, the TreeView requires the following classes to be defined:

1. Your tree node that will hold the data of each tree item:
private class Node {

private final Node parent;
private final String word;
private List children = new ArrayList();

Node(Node parent, String word) {
this.parent = parent;
this.word = word;
if(parent != null) {
parent.children.add(this);
}
}

public Node getParent() {
return parent;
}

public Collection getChildren() {
return new ArrayList(children);
}

public boolean hasChildren() {
return children.size() > 0;
}

public void setChildren(Collection newChildren) {
if(newChildren != null) {
children = new ArrayList(newChildren);
}
}

public String getWord() {
return word;
}

}
Please note that this class can be whatever class you require, this is only an example.

2. A tree content provider that will provide the content for the tree:
private class NodeContentProvider implements ITreeContentProvider {

@Override
public Object[] getChildren(Object element) {
return ((Node)element).getChildren().toArray();
}

@Override
public Object getParent(Object element) {
return ((Node)element).getParent();
}

@Override
public boolean hasChildren(Object element) {
return ((Node)element).hasChildren();
}

@Override
public Object[] getElements(Object inputElement) {
return (Object[]) inputElement;
}

@Override
public void dispose() {
// unused
}

@Override
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
// unused
}

}

3. The label provider that will provide the label for each item in the tree:
private class NodeLabelProvider extends LabelProvider {

private final TreeViewer viewer;

NodeLabelProvider(TreeViewer viewer) {
this.viewer = viewer;
}

@Override
public String getText(Object element) {
Node node = (Node) element;
return node.getWord();
}
}

I'll create a FilteredTree, but since it makes use of TreeView, using only a TreeView is trivial:

PatternFilter patternFilter = new PatternFilter();
FilteredTree filteredTree = new FilteredTree(cTree,
SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CHECK,
this.patternFilter);
filteredTree.setInitialText("type your filter text here");
TreeViewer treeViewer = filteredTree.getViewer();

// Assign the label provider
treeViewer.setLabelProvider(new NodeLabelProvider());

// Assign the content provider
treeViewer.setContentProvider(new NodeContentProvider());

// Populate the tree with elements
Node ex1= new Node(null, "Example 1");
new Node(ex1, "Example 1.1");
new Node(ex1, "Example 1.2");
new Node(ex1, "Example 1.3");
Node ex2= new Node(null, "Example 2");
new Node(ex2, "Example 2.1");
Node[] nodes = Node[] {ex1, ex2}
viewer.setInput(nodes);

// Event for item selection
treeViewer.getTree().addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
TreeItem item = (TreeItem) event.item;
Node node = (Node)item.getData();
// Manually Expand
treeViewer.expandToLevel(node, 1);
treeViewer.update(node, null);
}
});

Please note that the tree selection event always expands the selected node, you may wish to retract it or do another operation, like check all its descendants.
This is actually quite simple, but I was calling treeViewer.expandToLevel with the TreeItem instead of using the Node object, and that was the cause of my problems.

If you're looking for a similar example but using custom images, check Eclipse Nuggets.
./M6

Mediocrity is a choice

As Seth Godin states on a small post, quality is the result of choices one get to make every day.
Here's the full post: On the road to mediocrity.

./M6

Success is a Continuous Journey

Business success is a continuous journey, not a destination. I've learned this long ago, but I couldn't say it better than Richard St. John:



It's not about falling, it's about getting up again...

./M6

RCP save workbench status

In Rich Client Platform (RCP) application, the workbench status can be easily saved and restored by simply including the snippet bellow in the ApplicationWorkbenchAdvisor class, that extends WorkbenchAdvisor.

@Override
public void initialize(IWorkbenchConfigurer configurer) {
super.initialize(configurer);

// tell eclipse to save workbench state when it quits
// (things like window size, view layout, etc.)
configurer.setSaveAndRestore(true);
}

This will automatically save the status of the workbench when the application is closed and will automatically restore that status when the application is executed again. The settings are saved on the [runtime-{your-product}]/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml file.

./M6

Selecting a value from a SWT CCombo on RCP

It looks like the CCombo custom SWT object lacks some selection functionality. I'm using a CCombo as a table cell editor on my Rich Client Platform (RCP) application and I've found out that it is (almost) impossible to detect the user selection with both the keyboard and the mouse.

The selection listener does not work as expected. Documentation says:
  • the widgetSelected method is triggered whenever a selection occurs in the control, i.e. when the user browses the option list this event is triggered;
  • the widgetDefaultSelected method is triggered when default selection occurs in the control, i.e. when the user selects an option from the list this event is triggered.
One might think, as I thought, that all one has to do is to catch the widgetDefaultSelected event and one would know which option the user has selected from the list.
This is only true when the user performs the selection using the keyboard, i.e. after browsing through the options list the Enter/Return key is pressed.
If the user decides to use the mouse, the widgetDefaultSelected event is not triggered at all, but widgetSelected is.

I though I could detect the user selection with the mouse listener. I was wrong. After trying a couple more possibilities, it turns out there's no (easy) way to detect if the user has performed a selection using the mouse...

So I had to do a workaround for it. Since the widgetSelected is triggered by the mouse clicks, I tried to use that event. Unfortunately the event has no real useful information, like if it was triggered by a right button mouse click. But fortunately, the CCombo object does have a couple of methods that allowed to infer that a selection has been made. In particular, it has a method to check if the options list is visible or not. Since a selection with the mouse makes the options list disappear, I've used it.

Here's the snippet:

// Selections events
combo.addSelectionListener(new SelectionAdapter() {
// Selection changed, check if the options are still visible
public void widgetSelected(SelectionEvent e) {
// If list is not visible assume that the user has
// performed selection with the mouse
if (!combo.getListVisible()) {
setEditionValue(combo);
}
}

// Option selected
public void widgetDefaultSelected(SelectionEvent e) {
// User performed a selection with the keyboard
setEditionValue(combo);
}
});
This is not a perfect solution, it's a workaround, but it's working just fine for me.

./M6

Current time as numeric value in R

To get the current time, just use the Sys.time() function, see the Sys package for more information.
To get the current time as a numeric value in R, just use unclass(Sys.time()).
This seems to be higher accurate, 0.01 seconds.

./M6

tofrodos package

Kubuntu does no longer has the "old" DOS tools. I needed to use the dos2unix command and I found out it was no longer part of the standard core installation. Obviously it's still available, so all I had to do was install the tofrodos package, just sudo apt-get install tofrodos and the problem is solved.

./M6

R Package with S4 Objects

I've finished the development of the (beta version) clustering algorithm on R for my MSc thesis and I'm releasing it for tests.

I've developed it mainly in Windows, but when it comes to the packaging part, I've switched to Linux. This is mainly because R packaging in Windows implies to install a lot of base Linux applications and tools on Windows. For those that wish to go that road, here's what you have to do: read Making tutorial about R Packages Under Windows: A Tutorial by Peter Rossi.
For everyone else, just boot your Linux.

Before I start, I took a look at Writting R Extensions. This is the first step for all that wish to build an R extension. A fast and easy way to know how to pack, is to read the An Introduction to the R package mechanism.

My implementation uses S4 objects, and that was a problem, since I had all kinds of warnings and errors during the package tests and installation. Here's the transcriptions of the post I've sent to the R-Help list asking for help:
Here's what I do:

*1.* in R console, I do and get:
> package.skeleton(name='remora')remora-package
Creating directories ...
Creating DESCRIPTION ...
Creating Read-and-delete-me ...
Saving functions and data ...
Making help files ...
Done.
Further steps are described in './remora/Read-and-delete-me'.
Warning messages:
1: In dump(internalObjs, file = file.path(code_dir,
sprintf("%s-internal.R", :
deparse of an S4 object will not be
source()able
2: In dump(internalObjs, file = file.path(code_dir,
sprintf("%s-internal.R", :
deparse of an S4 object will not be
source()able
3: In dump(internalObjs, file = file.path(code_dir,
sprintf("%s-internal.R", :
deparse of an S4 object will not be
source()able
4: In dump(internalObjs, file = file.path(code_dir,
sprintf("%s-internal.R", :
deparse of an S4 object will not be source()able


I don't know why I get these warnings. I've followed R
implementation rules and the S4 objects work fine.


*2.* Performing the 'R CMD build remora' command I get:

* checking for file 'remora/DESCRIPTION' ... OK
* preparing 'remora':
* checking DESCRIPTION meta-information ... OK
* removing junk files
* checking for LF line-endings in source and make files
* checking for empty or unneeded directories
* building 'remora_1.0.tar.gz'

And the remora_1.0.tar.gz file seems ok.

*
3.* Performing the 'R CMD check remora' command I get:

* checking for working pdflatex ...sh: pdflatex: not found
NO
* checking for working latex ...sh: latex: not found
NO
* using log directory '/home/fmm/thesis/R/src/remora.Rcheck'
* using R version 2.8.1 (2008-12-22)
* using session charset: UTF-8
* checking for file 'remora/DESCRIPTION' ... OK
* checking extension type ... Package
* this is package 'remora' version '1.0'
* checking package dependencies ... OK
* checking if this is a source package ... OK
* checking for executable files ... OK
* checking whether package 'remora' can be installed ...
ERROR
Installation failed.
See '/home/fmm/thesis/R/src/remora.Rcheck/00install.out'
for details.

*4.* the log file contains:

* Installing *source* package 'remora'
...
**
R

**
data

** preparing package for lazy
loading
Error in parse(n = -1, file = file) : unexpected '<' at 745:
`.__C__remoraConfiguration` <- 746: <> -> code2LazyLoadDB
-> sys.source -> parse Execution halted
ERROR: lazy loading failed for package
'remora'
** Removing
'/home/fmm/thesis/R/src/remora.Rcheck/remora'
fmm@Darkmaster:~/thesis/R/src$ grep -i __C__remoraConfiguration *
fmm@Darkmaster:~/thesis/R/src$ grep -i __C__remoraConfiguration */*
remora.Rcheck/00install.out:745: `.__C__remoraConfiguration`
<- remoraConfiguration is a constructor for the
remoraConfiguration S4 object.
# # Class configuration definition.
# CLASS_REMORA_CONFIGURATION <- "remoraConfiguration" class_configuration
<- setClass(CLASS_REMORA_CONFIGURATION, representation(
number_clusters = "numeric", class_name = "character",
weighting_function="character", scale_variance="logical", s="numeric",
d="numeric", alfa="numeric", eta = "numeric", niter="numeric",
niter_changes="numeric", perform_sum="logical", verbose="logical"),
prototype = list(number_clusters=numeric(), class_name=character(),
weighting_function=character(), scale_variance=logical(),
s=numeric(), d=numeric(), alfa=numeric(), eta=numeric(), niter=numeric(),
niter_changes=numeric(), perform_sum=logical(), verbose=logical()))
# # Builds a Remora configuration object.
# # [...]
# remoraConfiguration <- function(number_clusters, class_name,
weighting_function = FUNCTION_REMORA_EUCLIDEAN,
scale_variance=TRUE, s_value = 0.001, d = 0.3, alfa = 0.9, eta = 0.01,
niter=-1, niter_changes=5, perform_sum = TRUE, verbose=FALSE)
{
result_configuration <- new(CLASS_REMORA_CONFIGURATION)
[...]
result_configuration
}

But, unfortunately, no help came from there...
I've never stopped the search for the answer, and I've finally found it. It's actually quite easy.
Instead of packing it from the current environment, I've just passed the package.skeleton the list of source files to build the package. Here's the small R script I've done to automate the packaging procedure for my "Remora" package:

cat('\nPacking Remora...\n')

file_lst <- character(5)
file_lst[1] <- '/home/m6/thesis/R/src/1_classes.r'
file_lst[2] <- '/home/m6/thesis/R/src/2_common.r'
file_lst[3] <- '/home/m6/thesis/R/src/3_model.r'
file_lst[4] <- '/home/m6/thesis/R/src/4_predict.r'
file_lst[5] <- '/home/m6/thesis/R/src/5_main.r'

package.skeleton(name = "remora", force = TRUE, namespace = TRUE,
code_files = file_lst)

cat('\nDone.\n')
Now it's time to go to the directory created, with the name of the package, from now on {package}, and edit the following files:
  • {package}/DESCRIPTION, the description of the package;
  • {package}/NAMESPACE, the list of functions and classes to export to the user;
  • {package}/man/{package}-package.Rd, the package help file, the \examples section must provide executable code, since R check command will execute this code;
  • {package}/man/{class_name}-class.Rd, the classes help files;
  • {package}/man/{function_name}.Rd, the functions help files;
All files under
/man/ are tex files and will be compiled to provide the functions help when invoked by the user.
It's only necessary to document the classes and functions that will be exported, i. e. exported in the
NAMESPACE file, since all the others will not be visible to the user. All the other .Rd files may be deleted.

After the package has been created, I've tested with the "R CMD check {package}
" command. My package name is "remora", so my command was "sudo R CMD check remora".
I had to run this command with the administration role, so I prefixed it with the
"sudo" command. I believe this is a characteristic of the Kubuntu distribution.

Finally I've build the package with the
"R CMD build {package}" command that created the tar.gz file for distribution.

To install it, just use the
"R CMD INSTALL {package}" command. I've entered R and it worked fine.
To uninstall just execute
"R CMD REMOVE {package}".

./M6

Bing

But It's Not Google.
That's Bing, the Microsoft rebranded and reformated search engine.

Bing has a nice background picture and allows me to search in English or Portuguese, but when there's a tie, the Portuguese result shows up first.

For what I could tell, it's definitely not Google.
Google is currently more than a search engine.
On Google I can ask simple questions like "4 times 5" or "1 euro in usd" and I get "4 times 5 = 20" and "1 Euro = 1.4225 U.S. dollars", this one depending on near real time
In Bing I only get regular search engine results.

Bing answer for 4 times 5.

When trying to search information in news group "linux.debian.laptop", I can do it in Google and since Bing knows it, Bing shows the Google Groups for "linux.debian.laptop".

As Seth Godin puts it, looks like Microsoft is trying to be the next Google, but currently here's already a next Google: Google.

Why should people change for something that works well to something that seems not to have a real distinguishing factor? At least for now, it's still, as alomost in Google, a Beta version. Even if Microsoft adds a few cool features, how much time it Google take to clone it and improve it?

I don't really know why Microsoft is investing so much time, money and effort in such a battle when they could be doing something remarkable.

Update
I've just discovered that actually Bing does some math and it knows how to answer 4 times 5.

What I also discovered is that, like many Microsoft applications, it thinks it knows what is best for me and, as always, it thinks wrong!
I've specifically have told Bing that I wanted results in English, but it ignored me and gave me results in Portuguese and looks like in Portuguese it was unable to compute 4 times 5.
Looks like Bing thinks that since I'm located in Portugal, I cannot ask questions in English! Is this stupid or what?
If it thinks it's smart enough to know what's best for me, I've asked the same question in Portuguese, "4 vezes 5" and, as I expected, it failed to answer the question.
Not very smart, Bing...

Bing is not Google, and they can say that again!
Keep up like that and definitely it will continue to live obfuscated by Google, like the "eternal wanna be"...

./M6