select the text item in table using code

General TRichView support forum. Please post your questions here
Post Reply
yh01110
Posts: 9
Joined: Thu Apr 21, 2011 12:43 am

select the text item in table using code

Post by yh01110 »

for example : text item in table a
table a in table b
how to select the text item using code. such as

Code: Select all

SRichViewEdit1.ActiveEditor.TopLevelEditor.SetSelectionBounds
Sergey Tkachenko
Site Admin
Posts: 17555
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

You need to make sure that this cell is being edited, then call SetSelectionBounds.

Your code:

Code: Select all

SRichViewEdit1.ActiveEditor.TopLevelEditor.SetSelectionBounds
selects a fragment in the top level editor, i.e. the editor that contains the caret. When the caret is in a table cell, this editor contains a content of this cell.

To answer with more details, I need to know what text you need to select.
yh01110
Posts: 9
Joined: Thu Apr 21, 2011 12:43 am

Post by yh01110 »

for example:
table-1 in page-1 and the text item-0 in cell[0,0],the current page is page2.When i use the following code ,the text item-0 can be selected ,but the srichviewedit will not jump to page-1.So i do't know how to write codes to let the srichviewedit jump to the table-1 .

Code: Select all

       
TRVTableCellData(tobj.Items[ListBox1.ItemIndex]).SetCursor(crDefault) ;
TRVTableCellData(table.Cells[0,0]).SetSelectionBounds(
       0,0,0,Length(TRVTableCellData(table.Cells[0,0])).GetItemTextW(0))+1);
yh01110
Posts: 9
Joined: Thu Apr 21, 2011 12:43 am

Post by yh01110 »

thanks ,The Problem has been solved .
just add this code

Code: Select all

SRichViewEdit1.ScrollToItem(table.Cells[0,0]),i);
Sergey Tkachenko
Site Admin
Posts: 17555
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Important:
1) before calling SetSelectionBounds in table cell, activate editing for this cell.
2) when the cell is being edited, all its items are moved to the cell inplace editor (temporary); because of this, cell.SetSelectionBounds fails, because no items in this cell. Use TCustomRVFormattedData(cell.GetRVData).SetSelectionBounds instead.

The correct code:

Code: Select all

var RVData: TCustomRVFormatteData;

table.EditCell(0, 0);
RVData := TCustomRVFormatteData(table.Cells[0,0]).GetRVData;
RVData.SetSelectionBounds(0, RVData.GetOffsBeforeItem(0), 0, RVData.GetOffsAfterItem(0));
JonRobertson
Posts: 164
Joined: Tue Nov 08, 2011 5:11 pm

Post by JonRobertson »

Sergey Tkachenko wrote:The correct code:

Code: Select all

var RVData: TCustomRVFormatteData;

table.EditCell(0, 0);
RVData := TCustomRVFormatteData(table.Cells[0,0]).GetRVData;
RVData.SetSelectionBounds(0, RVData.GetOffsBeforeItem(0), 0, RVData.GetOffsAfterItem(0));
Thank you, this was very helpful. Although I had to use TCustomRVFormattedData.

I'm using this to set the user's position within a table via code. Calling EditCell causes OnCellEditing to be called. This makes sense, but throws a small wrench in my design.

I have a table with multiple "notes". Each note is saved as a separate RVF. The table has two columns and one row for each note being saved. The left column is basically a header identifying the note to the right. The right column contains the notes.

I want to use OnCellEditing to keep track of which notes the user has modified. Is there another way to do this?

The problem I'm having now is that I don't want the code snippet above to signal that the user has modified a note, which it currently does since OnCellEditing is called. I tried setting a flag that OnCellEditing could check. But now my problem is that if the user does proceed with editing the contents of the current cell, OnCellEditing is not called again.

I assume that I can't set focus in a table cell without OnCellEditing being called.

And I assume that I can't determine if a cell's contents have been modified without using OnCellEditing or comparing the stored RFV against the RFV of the cell.

Any suggestions?

Thanks!
Sergey Tkachenko
Site Admin
Posts: 17555
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

While you select in a cell yourself, you can set some flag in your application.
In OnCellEditing, you can check this flag and do not mark this record as modified if it is set.
JonRobertson
Posts: 164
Joined: Tue Nov 08, 2011 5:11 pm

Post by JonRobertson »

Sergey Tkachenko wrote:While you select in a cell yourself, you can set some flag in your application.
In OnCellEditing, you can check this flag and do not mark this record as modified if it is set.
Yes, that seems obvious. But as I mentioned above, that doesn't work. Consider the scenario:
  • Set a "Setting Selection Flag".
    Call EditCell.
    In OnCellEditing, notice Setting Selection Flag is set, so don't set "Cell Modified Cell" flag.
    Call SetSelectionBounds.
    Now user modifies cell.
    OnCellEditing is not called because it was already called when EditCell was called.
    This logic doesn't catch that the user modified the cell's contents.
I'll create a demo app if I need to, but I'd rather not.

The upper two-thirds of my form has different panels of static information. The bottom panel of the form has a RichView with a table containing notes for each panel above. The left column contains a protected heading indicating which panel the note is associated with, while the right column contains the user modifiable note.

When the user clicks in one of the upper panels, I want to set focus within the cell that contains the note for that panel. I've got that working.

Each note is saved as a separate document. And for each note, I need to detect whether the user modified the note.

The user could jump between various panels/notes without making a single change. But since SetSelectionBounds requires EditCell to be called, and OnCellEditing is only called when the Cell initially goes into Edit mode, then I can't use OnCellEditing to detect when the user is actually making changes. Note I'm not complaining about OnCellEditing's behavior. It makes sense, although the event could be named OnBeginCellEditing, OnStartCellEditing, or something similar, to indicate its true behavior.

An OnCellChanging event would be ideal I think, but there's not one.

While writing this, I just found InplaceEditor. Perhaps in OnCellEdit I can set InplaceEditor.OnChange to another event that would tell me if the user actually changed the cell. I'll give that a shot.

If there is a better suggestion, I'm still interested in hearing it. :wink:
JonRobertson
Posts: 164
Joined: Tue Nov 08, 2011 5:11 pm

Post by JonRobertson »

My apologies for hijacking this thread. I should have started a new one. :(
JonRobertson wrote:While writing this, I just found InplaceEditor. Perhaps in OnCellEdit I can set InplaceEditor.OnChange to another event that would tell me if the user actually changed the cell. I'll give that a shot.
The documentation states that OnChange and OnChanging are members of TCustomRichViewEdit. While that is true, they are protected members and are not accessible via TCustomRichViewEdit.

I can cast InplaceEditor to a TRichViewEdit, which is fine since the latter simply publishes properties that are protected in TCustomRichViewEdit. But the documentation is wrong, from RichView users' point of view.
JonRobertson
Posts: 164
Joined: Tue Nov 08, 2011 5:11 pm

Post by JonRobertson »

JonRobertson wrote:While writing this, I just found InplaceEditor. Perhaps in OnCellEdit I can set InplaceEditor.OnChange to another event that would tell me if the user actually changed the cell. I'll give that a shot.
That doesn't work, as OnCellEditing is called before InplaceEditor is created. Again, that makes sense, as I could set AllowEdit to False in OnCellEditing.

But I'm out of ideas at this point. Looking forward to any suggestions you may have.

Thanks
JonRobertson
Posts: 164
Joined: Tue Nov 08, 2011 5:11 pm

Post by JonRobertson »

JonRobertson wrote:But I'm out of ideas at this point. Looking forward to any suggestions you may have.
I found a solution that works well. In TRichViewEdit.OnChange, if InplaceEditor is assigned, then I use GetCellPosition to determine which cell the user is changing.

Please let me know if you have any concerns with this approach. Thanks again.
Sergey Tkachenko
Site Admin
Posts: 17555
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Make sure that you process changes applied to selected cells (if multiple cells are selected) and to all cells (if the whole table is selected) correctly.
JonRobertson
Posts: 164
Joined: Tue Nov 08, 2011 5:11 pm

Post by JonRobertson »

Thanks for mentioning this.

When multiple cells are selected, I'm now using IsCellSelected to determine which cells are selected.

When the entire table is selected, IsCellSelected returns False for every cell. I've looked for a way to detect whether the entire table is selected. I thought I could use GetSelectionBounds, but I'm not sure my assumptions are correct.

When I call GetSelectionBounds with Normalize = True, the start/end item/offset values are the same when the entire table is selected and when only some of the cells are selected.

When I call GetSelectionBounds with Normalize = False, there is a slight difference. StartItemOffs equals 0 when entire table is selected but equals 1 when only multiple cells are selected.

Note the table is the only item in the RichView.

In this scenario, can I rely on StartItemOffs and EndItemOffs to determine if the entire table is selected? (0 and 1, respectively) versus partially selected (1 and 1, respectively)?

Or is there a better method? I've searched the help and the forums but haven't been able to find it. :(

Thanks
Sergey Tkachenko
Site Admin
Posts: 17555
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

A table is selected completely, if it is inside the range returned by its parent RichViewEdit's GetSelectionBounds.

The offset before the table = 0, after the table = 1.

Please retest again. I tested in your sample project, it is returned as expected.
When the table is selected completely:
- if Normalize=True, GetSelectionBounds always returns StartItemNo=EndItemNo=0, StartOffs=0, EndOffs=1.
- If Normalized=False, GetSelectionBounds returns StartItemNo=EndItemNo=0, and either (StartOffs=0, EndOffs=1) or (StartOffs=1, EndOffs=0), depending on the selection direction.

There is another possibility: when all table cells are selected, the table looks like if it is selected completely. In this case, GetSelectionBounds returns the position either before or after the table, and IsCellSelected must return True for all cells.
JonRobertson
Posts: 164
Joined: Tue Nov 08, 2011 5:11 pm

Post by JonRobertson »

Sergey Tkachenko wrote:There is another possibility: when all table cells are selected, the table looks like if it is selected completely. In this case, GetSelectionBounds returns the position either before or after the table, and IsCellSelected must return True for all cells.
That was it.

Once again, thank you for knowing and supporting your components so well. :)
Post Reply