Re: O$: making a headed list data driven
Hi Doug
I wonder if your considerable generosity in sharing your insights would
extend to putting up a sample library showing this headed list technique,
for the benefit of this of us who simply cannot travel.
(I would love to go to another conference one day, but is ain’t going. to
happen!)
Best regards
On Sat, Aug 12, 2017 at 6:50 PM, Bob Fiering <bob@maxolution.nl> wrote:
> Great Explanation Doug.
> Some parts I am already using in my program, but there are parts that
> sounds very interesting.
> I will ask you more about this at Euromnis 2017.
>
> Best regards,
>
> Bob
>
>
>
> > Op 11 aug. 2017, om 15:35 heeft Doug Easterbrook <doug@artsman.com> het
> volgende geschreven:
> >
> > hi Nick/Ken
> >
> > all of our headed lists are build in a data driven way from the query
> behind the list. To assist with that, we have a data dictionary
> containing all field names and some additional parameters about the field.
> Our dictionary is fairly complete an we store the data in the $info
> property of a file class (yes a file class), so that means for every table
> definition in the postgres database, we also have a file class lying around
> where we can add feature to the field.
> >
> > This makes adding windows and managing listsn in a table driven way very
> easy.
> >
> >
> > The general gist is:
> >
> >
> > Schema Class for a table might have:
> >
> > table MyTable:
> > Field1 char(10000000)
> > Field2 number long
> > Field3 boolean
> > etc
> >
> > File class called myTable also has the same fields.
> >
> > Field1 char(10000000)
> > Field2 number long
> > Field3 boolean
> >
> >
> > Query Class for myTable might only have some of the fields from that
> table, and possible fields from another table if its a talbe join.
> >
> > eq query might have:
> > Field1
> > Field2
> >
> >
> >
> > Why is this important to have a file class. it isn’t really, but there
> are lots of old omnis ways to conveniently get data easily from a file
> class like below. if I can figure out the file name, type, subtype, I
> can also get the $info property
> >
> > ‘pField’ is the name of a field in ANY file class
> >
> > Calculate FileName as [pField].$class().$name
> > Calculate type as $clib.$files.[FileName].$objs.[pFieldName].$objtype
> > Calculate subtype as $clib.$files.[FileName].$objs.
> [pFieldName].$objsubtype
> >
> >
> >
> > so now about the $info property — its a binary field, which means we
> can store anything in there. if you wanted to implement a rudimentary
> dictionary, you could stick into that binary field some things like:
> >
> > 1) normally visible in a list
> > 2) can never be displayed in a list
> > 3) left, centre or right aligned
> > 4) currency field
> > 5) typical display width
> > 6) the name of the field on the top f the headed list
> > 7) the log help description of the field
> > 8) more stuff if you want.
> >
> > Full disclosure, we have about 20 different attributes on each field in
> our data dictionary. We actually store the entire dictionary at the file
> level $info, rather than the field level — but I’m using the field level
> $info for illustration purposes. Reasons — thats a discussion on a data
> dictionary at euromnis.
> >
> >
> >
> >
> > at this point, we now have lots of knowledge about fields and behaviour.
> >
> >
> >
> >
> >
> >
> >
> > The general concept behind each list on a window is.
> >
> > do iList.$definefromsqlclass(‘myTable’)
> > set reference iListFieldRef as reference to the headed list
> >
> >
> >
> > now I have to make the headed list on the window have columns that
> correspond to the table class ‘iList’. so I simply do somerthing like
> this from the window. it calls the table class and asks the table class
> for ‘myTable’ to set up the headed list.:
> >
> > do iList.$makeColumnsForHeadedList(ilistFieldRef)
> >
> >
> > in makeColumnsForHeadedList, it does a bunch of work like:
> >
> > loop columns in the table class. eg:
> >
> > for loop 1,$cinst.$colcount
> > calc columnNumber as columnNumber+1
> > calc columnCalculation con(columnCalculation,chr(9),’
> jst(ilist.Fieldname’,’format’))
> > calc columnNames as con(columnNames,chr(9),ColumnNameFromDataDict)
> > calc columnWidths as con(columnWidths,’,’,widthOfCOlumnFromDataDict)
> > calc columnsVisible as con(columnsVisible,’,’,true or false from data
> dict)
> > end for
> >
> > The goal is to make a VALID string for each of the options for a headed
> list that are below and then you tell the list …
> > a) thats how I look
> > b) here are my columns
> > c) here is what we call then on the top of the headed list
> > d) here are the widths
> > e) here is what is visible and what is not (this is super powerful –
> I have items in lists that users can’t see, ever)
> > f) here is the order that the columns appear on the list
> >
> >
> >
> > Calculate pRefHeadedList.$colcount as columnNumber
> > Calculate pRefHeadedList.$calculation as columnCalculation
> > Calculate pRefHeadedList.$columnnames as columnNames
> > Calculate pRefHeadedList.$columnwidths as columnWidths
> > Calculate pRefHeadedList.$columnsvisible as columnsVisible
> > Calculate pRefHeadedList.$columnscontextmenu as columnsContextMenu
> > Calculate pRefHeadedList.$displayorder as columnDisplayOrder
> >
> >
> >
> >
> > back to the columnDisplayOrder . we default that to the order of
> the fields in the query class. but we let people drag columns around and
> we let people make some columns visible or hidden. so all we have to do
> is fetch the
> >
> > $displayorder from the list and save it
> > $columnsvisible and save it
> >
> >
> > and we now have preferences for each list for each user so that when the
> application wakes up for that user, the columns go back to the way they
> last looked at them.
> >
> >
> >
> > how do you save these values or implement sorting….
> >
> > our headed list window superclass deals with all these methods. some
> are used to sort the list. some are used to track that the user changed
> the order of columns (in which case we save the display order and
> visibility), etc.
> >
> > events tackled in the headed list follow .
> >
> > On evHeadedListEditFinished,evHeadedListEditFinishing,
> evHeadedListEditStarting
> > On evHeaderClick ;; Parameters – pColumnNumber
> > On evDrop ;; pEventCode pDragType pDragValue pDragField
> > On evClick ;; Event Parameters – pRow ( Itemreference )
> > On evDrag
> > On evDoubleClick ;; Event Parameters – pRow ( Itemreference )
> > On evHeadedListDisplayOrderChanged,evHeadedListHeadResize
> >
> >
> >
> >
> >
> > so far so good:
> > 1) a table class
> > 2) a dictionary
> > 3) we can build the headed list display headers to be what we want
> > 4) we can have actions on the list
> > 5) we can save the order of the display quite easily.
> >
> >
> >
> >
> >
> > Ken threw in something about having links in lists in his note.
> This is where ‘styles’ come in.
> >
> > you can either make the columnCalculation smarter so that it makes
> things look a certain colour or underline or what have you (test is out my
> manually editing a link)
> >
> > OR
> >
> > you can put the style in the data itself. There is a case to be made
> for doing one or the other or both.
> >
> >
> > eg, if a column is always a link, then the calculation in the HEADER for
> that column could be (this is shortened for clarity)
> >
> >
> > con(style(blue,underline),ilist.FieldwithURL,style(black,plain))
> >
> >
> > that means if there is a link, then it looks like a link.
> >
> > if you wanted currency to be red if negative, green if positive, null
> if empty, then go whole hog on formatting .. in other worded whatever
> you can do with a pick, style, con, jst, or any other omnis function or
> call back, you can do in the column.
> >
> > pick(ilist.field>0,con(style(red),ilist.field,style(black),
> con(style(green),iList.field),style(black)))
> >
> > or if you are a fan of common helper functions, translate the above into
> some common code that formats different types of fields in a way that you
> can adapct it in the common function easly
> >
> > $ctask.myFormatterCode,$format(iList.Field,’fielType’)
> >
> >
> >
> >
> >
> >
> >
> > there are ways to make the headed list auto-extend and I think there are
> ways to make certain columns enterable. We don’t do much of that as we
> tend to open a detail window to edit the line … but I have toyed with
> that a number of years ago.
> >
> >
> >
> >
> >
> > so, thats the gist of making a headed list data driven. it was a
> little bit of work to hash it out in the beginning some eons ago, but now
> that we have, we can make new subwindows with lists in them fully
> functional very quickly. It generally takes about an hour to wire in a
> window and fully test it. This is because the process is:
> >
> > 1) make a query
> > 2) make a table class
> > 3) create the joins in the table class if more than one physical table
> > 4) make a new sub widow containing the list and tell it which tableclass
> it is using
> > 5) stick list subwindow into main window
> > 6) make subwindow properly extend as window is resized
> > 7) decide what to do on click and couble click
> > 8) ** this takes most of the time — put in business logic specific to
> window
> >
> > and with all that we get our standard functionality that we’ve added
> over the years of
> > – list sorting
> > – exporting to excel/tab delimited, csv
> > – double click to edit a line
> > – context menu to delete lines
> > – print list as shown
> > – print custom reports
> > – drag/drop other data onto list
> > – and much more
> >
> >
> >
> >
> >
> > I hope this helps a little data dictionary plus list subwindow +
> building columns dynamically goes a long way to making windows easy to make.
> >
> >
> >
> >
> > If anybody wants to see how we really did it and I’ll give away some of
> our key classes, grab me at euromnis in Arnhem this year and I’ll be happy
> to run through the concepts. Some of you have been to my architecture
> session already have this code in our table classes and list windows
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > Doug Easterbrook
> > Arts Management Systems Ltd.
> > mailto:doug@artsman.com
> > www.artsman.com
> > Phone (403) 650-1978
> >
> >> On Aug 10, 2017, at 9:03 AM, Nick Renders <omnis1@arcict.com> wrote:
> >>
> >> Hi Doug,
> >>
> >> Excuse my language, I’ll try to be more careful and not use the CG word.
> >> I blame Hollywood for desensitising me, really.
> >>
> >> —— the following email is rated PG13 for some profane Omnis language ——
> >>
> >> I agree with you on Headed Lists. We use them 99% of the time as well
> and it looks like we can do a whole lot more with them. Thanks for the
> tips, I’ll have to look into moving columns and saving the list’s layout
> for each user.
> >>
> >> But there are those few cases where it makes sense to use a C-Grid
> instead. I just never realised it was so difficult to add a column in the
> middle. I figured I was overlooking something, but guess not. I’ll drop a
> little enhancement request with Omnis Support Germany, see if I can stir
> the pot.
> >>
> >> Cheers,
> >>
> >> Nick
> >>
> >>
> >> On 7 Aug 2017, at 16:06, Doug Easterbrook wrote:
> >>
> >>> hi nick.
> >>>
> >>> you said two dirty words as far as your question went. Complex Grid.
> >>>
> >>>
> >>> so be sure, complex grids are useful in any application and we have 4
> places that we use them. They are fantastic for a complicated multi line
> display with large icons and entry fields — however the limitation about
> them is .. changing them involved work.
> >>>
> >>>
> >>> on the other hand, a headed list box offers a whole lot of good so we
> use it in about 99% of our application. things such as:
> >>> easily hiding and showing columns
> >>> easily dragging columns from one place to another
> >>> easily extending the application if you add one more column to your
> list
> >>> ability to fix the first few columns in a list so that they can’t be
> scrolled off window
> >>> some ability to do entry into some columns
> >>> you can display small icons and change colours on list lines to
> highlight important features
> >>>
> >>> we have all our headed lists composed from a table class so that we
> save the last look of the list for each user and restore that when they
> next log in. adding a new column to the list for is simply:
> >>> add the field to the query class
> >>> update the fields visibility in our data dictionary
> >>> done — there are no further coding changes, or window changes at all
> >>>
> >>>
> >>> I find that a headed list is pretty easy for our customers to grasp
> and they like the ability to move columns. it far outweighs complex grid —
> which we have to program everything for.
> >>>
> >>>
> >>> when we converted from the classic world, we started off thinking
> everything was a complex grid, simply because thats what we were used to…
> >>>
> >>> until we discovered the sheer joy and simplicity of the headed list.
> its my favourite studio interface object.
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>
> >>> Doug Easterbrook
> >>> Arts Management Systems Ltd.
> >>> mailto:doug@artsman.com
> >>> www.artsman.com
> >>> Phone (403) 650-1978
> >>>
> >>>> On Aug 4, 2017, at 1:54 AM, Nick Renders <omnis1@arcict.com> wrote:
> >>>>
> >>>> Hi *
> >>>>
> >>>> I have a newbie question about the complex grid.
> >>>>
> >>>> Whenever I want to add an extra column in design mode,
> >>>> I update the $columns property of the object. Omnis
> >>>> adds a divider at the end, and I can start adding objects
> >>>> in the new column.
> >>>>
> >>>> But how do I add a column in between 2 other columns?
> >>>> Is there perhaps some way to re-order the columns in a
> >>>> complex grid?
> >>>>
> >>>> The only way I have found is to drag fields from one
> >>>> column to another, but that is really tedious work.
> >>>> Am I missing something obvious?
> >>>>
> >>>> Best regards,
> >>>>
> >>>> Nick Renders
> >>>>
> >>>> _____________________________________________________________
> >>>> Manage your list subscriptions at lists.omnis-dev.com
> >>
> >>
> >> _____________________________________________________________
> >> Manage your list subscriptions at lists.omnis-dev.com
> >
> > _____________________________________________________________
> > Manage your list subscriptions at lists.omnis-dev.com
>
> _____________________________________________________________
> Manage your list subscriptions at lists.omnis-dev.com
>
_____________________________________________________________
Manage your list subscriptions at lists.omnis-dev.com