Wednesday 23 December 2015

Drag and drop

Yesterday I read an interesting article about drag and drop in Uniface, aptly named Drop It Like It's Hot.  

It actually goes into plenty of detail about how to add drop areas into your own Uniface forms, which is something I'd definitely like to try some time.  But what really interested me was the opening paragraph...

What very little people know is that in the Import Repository Objects component there is a small section where you can drag your export files from Windows Explorer. After you drop them, the File name box is updated with the list of files that you dropped. The red section is where the drag-and-drop field is located.


I tried this today and it definitely works.  You learn something new every day!

Summary: You can drag and drop export files onto the Import Repository Objects popup, which is really quick and convenient.

Tuesday 10 November 2015

Modernising Uniface - part 3

Over the past couple of weeks I have posted about Modernising Uniface (and here), and this is the third and final post in this series.

The third post from Theo Neeskens was primarily concerning the new flat buttons, which look like this...



As you can see, the new flat blue buttons, on a white background, are on top of the old grey/grey.

The first thing they needed to do was categorise the different painted button types, and they came up with five...
  1. IDFButtonBottom - for the big buttons at the bottom of dialogs
  2. IDFButtonSide - for the big buttons at the right-hand side of dialogs
  3. IDFButtonSpecial - for the other buttons
  4. IDFButtonImage - for the small buttons without labels (eg. ">>")
  5. IDFButtonHeader - for the buttons which make up the header on simulated grids

So then there are a few jobs that needed to be done...
  • Change the properties in the configuration file for these widget types
  • Match modelled widgets with painted widgets
  • Set the properties on the painted buttons
  • Set the properties on the modelled buttons



Again, many of the these jobs were achieved with tools, and all of these have been provided in a zip file, to be downloaded and modified if you wish, but not supported by Uniface and used at your own risk.

The full blog post is definitely worth checking out, including the "Wishes" section at the end... Modernizing Uniface 9.7: The buttons


Summary: Uniface has successfully (in my opinion!) modernised it's IDE in version 9.7, meaning we don't have to wait for Uniface 10.

Wednesday 4 November 2015

Modernising Uniface - part 2

I posted last week about Modernising Uniface, which included my comments about Theo Neeskens post on UnifaceInfo.com.  I received some comments that I was talking purely about the IDE, and not the language itself.  So let me start by stating that this post of about the modernisation of the IDE, and not the language itself.

This time the post is all about the effort it took to make the seemingly simple move from grey backgrounds (which psychologically make software feel outdated) white clean, clear, white backgrounds, like this...

For both of these dialogs, the older grey version sits behind the newer white version.  You can also see the buttons have changed, but we've been promised more about those in the next blog post.


The main problems they hand with this change included...
  • Forms having index, foreground or background colour set
  • Painted entities having index, foreground or background colour set (and being painted at least 3 characters wide)
  • Entities having foreground or background colour set in the model
  • Grids not having borders
  • Multi-occurrence entities not having borders

A couple of these have been resolved by making new properties available, but all of them required fix programs to find the affected items and update them to the new properties.  All of the tools have been provided in a zip file, to be downloaded and modified if you wish, but not supported by Uniface and used at your own risk.

I've had my hands on Uniface 9.7 now (which I hadn't when I wrote the first post) and I can say that it definitely feels more up-to-date, and I agree that the white backgrounds and blue buttons are a large part of that.  We've actually been changing our web offering to a similar colour scheme over the past few months, so I can't disagree with their choice!

Again, the full blog post is definitely worth checking out... Modernizing Uniface 9.7, Part 2.


Summary: Uniface is modernising it's IDE, and we're not going to have to wait for Uniface 10 to get in on the action.

Thursday 15 October 2015

Modernising Uniface

Uniface have been putting a lot of work into the new Uniface 10 IDE, and this is something I'm looking forwards to getting my hands on, but it could be a while yet.  Good things come to those who wait, they say.

Well the good news is that the delays in Uniface 10 have led to the decision to release a Uniface 9.7.  Whilst they may be planning to put limited time into this, whilst focusing their efforts on Uniface 10, it looks like they have big plans to modernise.

In the first of a 10 part series, Theo Neeskens has outlined the objectives and the first set of changes - the start screen.

The objectives were straightforward enough...

  1. New start page - Windows 10-esque - big change.
  2. Change grey backgrounds to white backgrounds.
  3. Use trendy flat buttons.
  4. Fresh look and new colour scheme - something different.

Looks like they met the objectives, based on these screenshots...



Now that's a radical change!  I think changes like this will be very well received, and help stop people getting such a negative first impression of Uniface as a language.

The full blog post is definitely worth checking out... Modernizing Uniface 9.7 in 10 easy steps.

Summary: Uniface is modernising, and we're not going to have to wait for Uniface 10 to get in on the action.

Friday 24 July 2015

Where to put your code

There's an interesting blog post by Dennis Vorst gone up on the Uniface.info blog, titled Where to put your code.  As the title suggests, it's about which places are best for different types of code, based on their content.  

There are a number of options; conceptual at the entity or field level, locally at the entity or field level, within the component, a local procedure or a global procedure.  All of these have their merits.  

I've posted my response, defending the mighty global procedure, but why don't you have a read and add your opinion in the comments?

Summary: Check out this blog post... http://unifaceinfo.com/where-to-put-your-code

Monday 29 June 2015

WCG Online

I must apologise, this is not a Uniface-related post.  That said, please read on!

World Community Grid enables anyone with a computer, smartphone or tablet to donate their unused computing power to advance cutting-edge scientific research on topics related to health, poverty and sustainability. Through the contributions of over 650,000 individuals and 460 organizations, World Community Grid has supported 24 research projects to date, including searches for more effective treatments for cancer, HIV/AIDS and neglected tropical diseases. Other projects are looking for low-cost water filtration systems and new materials for capturing solar energy efficiently.

Active projects include... 
  • Outsmart Ebola Together
  • Uncovering Genome Mysteries
  • Mapping Cancer Markers
  • The Clean Energy Project - Phase 2
  • FightAIDS@Home.

If you're not already a member, you can sign up here.

I have just launched a companion site; WCG Online...



This site is designed to give you, a valued member of the community, access to some more detailed statistics, as well as some lovely pretty graphs.  It requires for username and a verifcation code, in order to fetch the relevant data.  Nothing is stored on my server, all data is stored in your brower's local or session storage.  This is then used to notify you of new milestones, such as badges earned.  It allows you to rename and hide devices, so if you've got multiple devices (two phones, a tablet, etc) you can give them more easily identifiable names, or hide them completely from the other pages.

The site is also designed to be fully responsive and mobile friendly, created from the ground up in jQuery Mobile.

The next part of the project is to create custom widgets that you can link to on your own site.  The offical site has widgets, but they use iframes and are rather basic.  So I'm hoping to create images, and give a lot more flexiblity.  Watch for those coming soon to WCG Online.

There is also a Play store app, which provides a shortcut to the website, and is free to download, if you're interested.

Saturday 2 May 2015

Performance of getitem

I've previously posted about how scanning is slow, and I stand by that.  But I've recently discovered that in some situations, it can be less slow than using getitem.  

I was doing a code review of some old code and found that it was using $scan in a situation where I thought you'd usually use getitem, and wondered why someone would have done it this way.  But before I replaced it, I wanted to check the performance to see what difference I would be making by changing it, and I was surprised by the results!

The code was designed to check if a variable matched one of a reasonably large number of items.  For this example, if stuck with 10 items...

  if ( temp = "ONE" | temp = "TWO" | temp = "THREE" | temp = "FOUR" | temp = "FIVE" | temp = "SIX" | temp = "SEVEN" | temp = "EIGHT" | temp = "NINE" | temp = "TEN" )
    ;testing condition
  endif

I could have used a line continuation marker, but you get the idea.

What the developer had done is replaced this set of conditions with a single $scan, like this...

  list = "|ONE|TWO|THREE|FOUR|FIVE|SIX|SEVEN|EIGHT|NINE|TEN|"
 
if ( $scan(list,"|%%temp%%%|") > 0 )
    ;testing condition
  endif

Note that this is not a Uniface list, a "bar" or "pipe" character has been used as the delimiter - this is placed at the beginning and end of the value to ensure it is not found as a sub-part of another longer value.  It This takes up a lot less space, and is perfectly readable, but I was concerned about performance.  

To test this, I wanted to make sure it was fair, so I decided to always check both the first and the last item in the list in each iteration.  I also wanted to test in a few different ways, and I came up with 4...

1) Set of conditions

  temp = "ONE"
  if ( temp = "ONE" | temp = "TWO" | temp = "THREE" | temp = "FOUR" | temp = "FIVE" | temp = "SIX" | temp = "SEVEN" | temp = "EIGHT" | temp = "NINE" | temp = "TEN" )
    ;testing condition
  endif
  temp = "TEN"
  if ( temp = "ONE" | temp = "TWO" | temp = "THREE" | temp = "FOUR" | temp = "FIVE" | temp = "SIX" | temp = "SEVEN" | temp = "EIGHT" | temp = "NINE" | temp = "TEN" )
    ;testing condition
  endif

2) $scan a bar delimited string

  list = "|ONE|TWO|THREE|FOUR|FIVE|SIX|SEVEN|EIGHT|NINE|TEN|"
 
if ( $scan(list,"|ONE|") > 0 )
    ;testing condition
  endif
  list = "|ONE|TWO|THREE|FOUR|FIVE|SIX|SEVEN|EIGHT|NINE|TEN|"
  if ( $scan(list,"|TEN|") > 0 )
    ;testing condition
  endif

3) getitem/id a Uniface list

  list = "ONE·;TWO·;THREE·;FOUR·;FIVE·;SIX·;SEVEN·;EIGHT·;NINE·;TEN"
  getitem/id temp,list,"ONE"
  if ( $status > 0 )
    ;testing condition
  endif
  list = "ONE·;TWO·;THREE·;FOUR·;FIVE·;SIX·;SEVEN·;EIGHT·;NINE·;TEN"
  getitem/id temp,list,"TEN"
  if ( $status > 0 )
    ;testing condition
  endif

4) $item a Uniface list

  list = "ONE·;TWO·;THREE·;FOUR·;FIVE·;SIX·;SEVEN·;EIGHT·;NINE·;TEN"
  if ( $item("ONE",list) != "" )
    ;testing condition
  endif
  list = "ONE·;TWO·;THREE·;FOUR·;FIVE·;SIX·;SEVEN·;EIGHT·;NINE·;TEN"
  if ( $item("TEN",list) != "" )
    ;testing condition
  endif


I wasn't really sure what I was expecting, but I thought the $scan would be the worst performance.  I tested over 2,000,000 iterations, and here's what I got...

1) Set of conditions: 37.30, 36.95, 37.83 = 37.36 secs
2) $scan a bar delimited string: 21.76, 21.97, 21.24 = 21.66 secs
3) getitem/id a Uniface list: 24.46, 24.22, 24.89 = 24.52 secs
4) $item a Uniface list: 22.65, 23.25, 23.47 = 23.12 secs

So the slowest was the set of conditions.  I didn't test it, but knowing that if statements shortcut I figure that if the item was always passing the first condition it would be quick, but because half of my test items were only passing the last condition, it would have to check each of the conditions in the set before it passed.

Although there wasn't a big difference, what surprised me is that the getitem/id and $item were actually slower than the $scan in this case.  I then remembered back to a conversation on the Uniface-L mailing list, which talked about how Uniface handles lists in the background.  The description there indicates that an array is built in the background, which means there is an upfront cost for calling getitem/id (or $item) once, but then if you're looping through it is much quicker to access the rest, because the array can be used.  However, because I'm rebuilding the list each time, that means the array needs to be rebuilt each time.  

This means that actually $scan can be used to improve the performance when checking that an item is in a list, as long as you're only checking this list once and it's not going to be re-used.  I expect there to be a point at which the number of times the list is re-used means that using getitem/id (or $item) would become better for performance.

Also, I've not tested different lengths of lists.  However, given the results and my reasoning for why the results ended up this way, I would have thought extending the list would simply emphasize the results.

Summary:  Checking if an item is in a list can be done a number of ways, and if it's being done a lot of times, performance can be eeked out by using a $scan, surprisingly!

Saturday 11 April 2015

Modernising the client application - icons in the menu

A lot of the Uniface development that I do these days is actually web development, which means I spend a lot of time with Javascript and JQuery, and less time with Uniface procscript.  However, we still have client applications as well, and they can look tired and dated, so anything we can do to make them look more modern, can be a big win!

This is a simple little trick that appeared in Uniface 9.6.  It's actually been around for a while in dropdown menus, first as an undocumented feature, and then documented in Uniface 9.5 - I wrote a blog post on this almost three years ago.  However, the same trick now works in menus.

You can reference images in the menu items like this...


You might not be able to read the image clearly, so the three menu items are...

  1. ^U_REM_SELECT·!Cu%t
  2. ^U_SAVE·!Copy
  3. ^U_INS_SELECT·!Paste

In this case, the image is at the start, with a gold-not (or gold-exclamation-mark) as a delimiter, and the menu item text after that.

This appears in the client application this this...



As you can see - lovely icons!  Please note that you would need these glyphs in your system for it to work, these are not provided as part of Uniface itself.  

You can include icons in one of two ways...

  • ^glyph - glyphs need to be compiled into UOBJ (always available and performs well).
  • @filename - images loaded from a fileserver (not always available and performs badly).

I would recommend the glyph option though, for performance and reliability.

You may also note that the percent character (%) can be used to denote which character should work when traversing the menu using the "Alt" key.  If you do not explicitly denote this, the first character will be used.

This is documented in the "Defining and Using Menus" section of the manuals, but can be hard to find unless you know what you're looking for!  It's worth reading this for more information though.

Summary:  It's possible to make the client application look a little more modern now by including icons in the menu bars.

Thursday 9 April 2015

Undocumented feature - current assignment file

One great feature of Uniface is it's great flexibility and configurability, through the use of different assignment (.asn) files.  These are used to define paths to the different runtime files and server locations, etc.  The problem can then come though, especially with multiple environments, that you don't know which assignment file you're using!

I wrote a post a while ago about the undocumented $assignments function, which allows you to get access to the assignment file settings that you are currently using, but this doesn't help you get to the filename itself.

One suggestion I've seen before is to add a logical to each assignment file which specifies the name/location of the file.  However, it's way too easy for someone to move, copy or rename the file and neglect to update the logical, and then worse than not knowing, you think you do know but the information you're being given is inaccurate.

Luckily Uniface 9.6.06 has solved this problem with a new undocumented feature of $processinfo...


  putmess $processinfo("cmdline")

This will put the command line used to access the application into the message buffer.  For example...


  "\\server\location\uniface\bin\uniface.exe" /asn=\\server\location\adm\uclidev.asn /ini=\\server\location\ini\me.ini APPSHELL


As you can see, the assignment file and ini file are both specified in the command line, along with the application shell as well.  This should give you all the information you need, although you'll need to do some string manipulation to pull out the bit(s) you want.

This was recently discussed on the UnifaceInfo.com forums, so you can check there for more context, and sign up if you haven't already!

Summary: You can access the current assignment file location, but accessing the command line, as long as you're happy to use an undocumented/unsupported feature.

Monday 30 March 2015

Indirection with dollar registers

Indirection in Uniface is a wonderful thing.  You can populate a local/component/global variable with a field name, and then use indirection to get the field value of the field that the variable references.  You can also use it to set the referenced field to a value, like this...

  fld1 = "fld2"
  @fld1 = "Test"
  if ( fld2 = "Test" )
    ;this will be true
  endif

In this example, using the "@" character to indicate indirection, it's the field which is referenced by "fld1" and not "fld1" itself which is updated.

You can even do recursive indirection, which is very cool!  Not something I've had a need for myself, but very clever all the same.

However, today I was trying to populate a register the same way, using code something like this...

  reg50 = "$50"
  @reg50 = "Test"
  if ( $50 = "Test" )
    ;this will be false!
  endif

In this example, the register was still blank (or whatever the register was before hitting this code).

To be fair, this is clearly stated in the Uniface manuals...

Only fields can be referenced indirectly; the name reached by the indirect reference cannot be a variable. The following example is incorrect because the indirection refers to a general variable rather than to a field:

$1 = "$99"

@$1 = "This string does not go to $99."


But I still wanted to be able to set registers in an indirect way, so I came up with this alternative...

  putitem/id list,"$50","Test"
  getlistitems/id list
  if ( $50 = "Test" )
    ;this will be true
  endif

This works by populating a list with the register and the value, and then uses getlistitems to populate them.  The "/id" mode copies items from the associative list into one or more fields, or registers in this case.

For example, you could use a simple for loop to clear out all of the dollar registers...

  for count = 1 to 99
    putitem/id list,"$%%count%%%",""
  endfor
  getlistitems/id list

This would set each of the 99 dollar registers to blank.

Summary: Indirection works great for fields, but not for registers - however, you can use getlistitems to achieve the same outcome.