Recent

Author Topic: Enabling/disabling treeview nodes according to the value of another node  (Read 2572 times)

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Dear ALL,

Hi! After a long time without much hassle, here am I again with one those boring spiny problems.

I have a (demo) application with a listview for displaying computer brands and a treeview for displaying (some of) their features. So, for each selected computer brand, its features are displayed as tree nodes, checked or unchecked according to the value of each feature. So far, so good, but I want to add a new functionality, that is, to make a feature 'controls' another, making it 'inapplicable' for some feature value. For example, if the feature 'soundcard' has the value 'absent' for a given computer, then the feature 'soundcard type' should be disabled (or indicated by a different icon).

For indicating how a given feature 'controls' another, I use a simple arbitrary notation like '2:5', in this case indicating that the second value of the feature controls the feature number 5. This is obviously confuse and my first attempt at implementing it has not been successful (see the attached screenshot). My demo code is also attached.

Could someone give a hand?

Many thanks in advance!

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #1 on: January 21, 2021, 05:03:44 pm »
I am not yet ready to answer you question, but I see some weaknesses in your data structure

* Don't use strings when you want to identify well-defined enumeratable properties. I would create an enumerated  type TFeatureKind = (fkQuantitative, fkQualitative) instead of using strings "quantitative" and "qualitative". This will help you avoid typos, and the compiler will tell you that something is misspelled.

* Don't use two identifiers for the same logical state. So, when a soundcard is "present" there is no need to have a node with "absent" - it's just the same, but inverse.

* Don't use checkbox icons for data which are exclusive. A processor is either a "8088", or a "80186", or a "80286" etc, but never two or more of them at the same time. Use a radiobutton icon instead (with that change I would even be willing to accept the "absent"/"present" issue.)

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #2 on: January 21, 2021, 07:29:00 pm »
Dear @wp,

Thanks a lot for your reply. I have no control over the data structure, which in fact is based on the DELTA (DEscription Language for TAxonomy) format (see https://www.delta-intkey.com/www/standard.htm for details), developed for use in botany and zoology.  My demo uses a subset of DELTA (emulated in memory, just for testing purposes) and I created that (naive) example using computer brands just for the sake of simplicity.

Best regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #3 on: January 21, 2021, 07:49:26 pm »
Treevieew nodes don't have property Enabled but they have property Visible. So you can hide the non-editable items - if it's acceptable for you.
Code: Pascal  [Select][+][-]
  1. TreeView1.Items[i].Visible:=False;
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #4 on: January 21, 2021, 08:01:39 pm »
Dear Blaazen,

Thanks for your suggestion, but unfortunately making a node invisible does not do. Perhaps I have wrongly used the the terms "enable/disable" - what I do really want is to change the icons of a node, based on a certain value of one of the other nodes.

Best regards,
« Last Edit: January 22, 2021, 12:36:54 am by maurobio »
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

paweld

  • Hero Member
  • *****
  • Posts: 996
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #5 on: January 21, 2021, 10:20:31 pm »
maybe something like that
« Last Edit: January 21, 2021, 10:26:35 pm by paweld »
Best regards / Pozdrawiam
paweld

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #6 on: January 21, 2021, 10:34:12 pm »
I have no control over the data structure, which in fact is based on the DELTA (DEscription Language for TAxonomy) format (see https://www.delta-intkey.com/www/standard.htm for details), developed for use in botany and zoology.  My demo uses a subset of DELTA (emulated in memory, just for testing purposes) and I created that (naive) example using computer brands just for the sake of simplicity.
Thanks for the simplified example, not being a biologist I would not have been able to understand the DELTA specification.

Let me describe your program in my words
- There are several "species" (here: computer models). They are listed in the ListView
- Each "species" has several predefined features.
- The names of these features are listed in the top-level nodes of the treeview.
- The values of each feature are given as subnodes of each feature node.
- There are two types of features:
  - enumerated features: each possible value is listed as a node, the current value is a checked node. The checked node is identified as the index in the list.
  - simple number features: it is a single subnode of the feature node showing the value directly

Your question: when a feature has a specific value other features do not exist; these values should be identified by a different node icon.

Your task is to create a ListView/TreeView presentation for some data specified in a DELTA file. Correct=

In this case, I think your program is basically correct. Shouldn't you find a specification in the DELTA file which features do not exist? Parse this data and find out which node index is not available - similar to what you do.

I am bit lost because i don't understand why you are not happy with your code...

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #7 on: January 22, 2021, 12:46:06 am »
Dear @wp,

You understood well the general issue, thank you. But I am not happy with my (demo) code simply because it is wrong. If you run the code, or just look at the screenshot I provided, you will see that: the "soundcard" feature is marked both "present and absent" (which is impossible), and the "soundcard type" is marked "soundblaster pro" - but it can take only one value (either "present" or "absent"), and if "absent", the attributes of the "soundcard type" feature should be all "disabled" (that is, indicated by the red cross icon).

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #8 on: January 22, 2021, 12:51:24 am »
Dear @paweld,

I just looked at the modification of the code you provided. That looks to solve my problem! But I will have to take a closer look at it.

Thank you very much!

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #9 on: February 11, 2021, 02:59:30 pm »
Hi,

The solution suggested by @paweld works great, but I now have a variation of the problem, for which I beg your help again. It is not really so complicated by I am somewhat at a loss because I cannot devise a simple way of handling it.

In my initial example, for indicating that a given feature 'controls' another, a simple arbitrary notation like '2:5' was used, in this case indicating that the second value (state) of a feature controls the feature number 5. So, if in a given computer brand the soundcard is absent, then the "soundcard type" feature is automagically disabled in the feature tree. The solution proposed by @paweld works fine when that state of a feature controls just one other feature (eg., 2:5). But it happens that I may cases in which a feature can control more than one other feature. So, alongside a "soundcard type", I can also have a feature "soundcard power", which should also be disabled in the feature tree if the soundcard is absent. In this case, the control rule becomes "2:5-6", indicating that state 2 controls features 5 and 6. In fact, I could even have a rule like "2:5-7", indicating that state 2 controls features 5, 6, and 7., and so on.

It seems clear to me that any modifications should be added to the method below:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.CheckInapplicables(SelectedIndex: integer);
  2. var
  3.   j, k, StateNo, FeatureIdx: integer;
  4. begin
  5.   if SelectedIndex >= 0 then
  6.   begin
  7.     for j := 0 to Length(Features) - 1 do
  8.     begin
  9.       if (Length(Features[J].Controls) > 0) and (pos(':', Features[J].Controls) > 0) then
  10.       begin
  11.         if TryStrToInt(Features[J].Controls.Split([':'])[0], StateNo) and
  12.           TryStrToInt(Features[J].Controls.Split([':'])[1], FeatureIdx) then
  13.         begin
  14.           if (StrToIntDef(Computers[SelectedIndex].attributes[j], 0) = StateNo) then
  15.             DiffrentIconChildState(FeatureIdx);
  16.         end;
  17.       end;
  18.     end;
  19.   end;
  20. end;

However, I could not come up with a clear way of implementing it. Could anyone give me a hand?

Thanks in advance!

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

egsuh

  • Hero Member
  • *****
  • Posts: 1289
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #10 on: February 11, 2021, 03:30:55 pm »
Actually this is quite complicated because this is not an issue of TControl, rather it is a data structure issue, I guess.

I'm not familiar with DELTA format, but it seems it contains all information on one species below the name of species. If then, why not re-draw all tree when an item in the ListView is selected? It will show all the features contained in the definition of the selected species.

If you have to show all available features just setting the image with X which is not applicable to the selected species, then first set all the images to not applicable image and then set all the applicable nodes to applicable image one by one based on the DELTA data.

If the premise that "it contains all information on one species below the name of species" is not true, you have to make a table which contains all the possible combination of features. For example,

               IBM     premium sound card           pwr 1000
               IBM     premium sound card           pwr  800
               IBM     normal sound card              pwr  750
               IBM     normal sound card              pwr  650
               DELL   premium sound card           pwr  900
               DELL   premium sound card           pwr  750
               DELL   normal sound card              pwr  700
               DELL   normal sound card              pwr  600
               DELL   No sound card           
             
Well if this is the case, complicated SQL statements may be necessary.



maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #11 on: February 11, 2021, 03:48:46 pm »
@egsuh,

Thanks for your comments. Notice that the simple, and very elegant, solution proposed by @paweld works fine! It just needs to be generalized for more than one FeatureIdx (which should become a list instead of a scalar variable).

Best regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

egsuh

  • Hero Member
  • *****
  • Posts: 1289
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #12 on: February 11, 2021, 04:14:03 pm »
@maurobio

Actually I have a project which require a similiar solution. I'm assessing whether DELTA is applicable to my problem as well. Your posts (and paweld's solution) are good hints for me.

paweld

  • Hero Member
  • *****
  • Posts: 996
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #13 on: February 11, 2021, 07:22:55 pm »
classes + FGL - sample in attachment
Best regards / Pozdrawiam
paweld

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: Enabling/disabling treeview nodes according to the value of another node
« Reply #14 on: February 11, 2021, 07:26:30 pm »
@egush,

I am glad to be of any help for your project! As a matter of fact, I am just working on a (Free) DELTA Editor, entirely written in Lazarus/FreePascal. It will be free and open source and will may find it useful.

Best regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

 

TinyPortal © 2005-2018