Skip to main content

JXTable - some grumbling...

30 replies [Last post]
Anonymous

Hi JDNC-Team,

it's exciting to see some real code and working examples with many new
features after a year of waiting.

Being a JTable freak the first place I went was the JXTable - very nice,
all those decorations :-) It looks like being the most mature of the
"collection views" (list, tree, combo), those will eventually be
Searchable as well?

I would like to comment on some design/implementation issues - though
I'm aware that the code is still raw, I view that more as a chance than
a obstacle. Basically they relate to TableColumnEx and its enhanced
responsibilities.

1) getting some responsibility to provide reasonable widths

A quote from getPrefWidth(..): "// .. do we want to calculate every
time?" - my answer to this is a clear "no" and going further even a
clear "never".

One reason is that the "pref" is a "preference" controlled by context:
one is the preference as a component might return in prefSize, the other
is the preference a user does express by resizing the column. The
TableColumn cannot decide which is meant, currently it assumes to be the
first kind of pref which makes is not-resizable with a prototype and the
table in autoresizeoff mode.

Another aspect is that there's need for something much smarter which
includes min/max sizes and resizing behaviour of the columns as well -
some means to really "layout" the columns. All size requirements might
depend on the TableModel. Too much burden for a simple data-storing
class, I think. Any effort to make it "smarter" will introduce
additional coupling into realms it should not have any knowledge of.

Yet another reason is that binding any tableModel-related "layout-info"
into a TableColumn is possible only after the table is filled with some
data and is lost whenever the model changes. That's at least annoying
though not un-resolvable.

2) taking control about the renderers to use

Until now JTable has full control about choosing the renderers. The
implemented strategy is to ask the column first which gives clients an
emergency hook - in my experience setting a renderer on the tableColumn
is rare event (most unliked because they are lost on model changes) and
used as a last resort, f.i. if choosing the renderer by column class is
not fine-grained enough. So the main route of choosing is through the
JTable's mapping of default renderes to column class.

TableColumnEx snatches that control from JTable if labelProperties are
applied, it insists on returning a renderer of its _own_ choosing if
none is set in the column. Tssss ...

3) back-referencing into JTable makes me feel very uneasy.

It's a necessity if the TableColumn is burdened with its new tasks.
Nevertheless it "smells" strongly on a general level, introducing a very
strong coupling somewhere hidden in the bowels. As a consequence,
ColumnModels are no longer shareable across tables. Which is a
showstopper in certain contexts (a lot of mine at least).

A lot of nagging - I know, but have seen it all, have been exactly there
half a year ago :-) - IMO moving those enhanced responsibilities into
the TableColumn is a dead end. An alternative is to move it out into a
dedicated handler which can be easily configured by client code at any
time and is used by the table (or some adapter) when it comes to
actually configuring the renderers/columns. Currently I'm tweaking
JXTable to use my approach - and it looks promising :-)

Amy, if you are interested, please pass me a note: I can mail you a link
to a not (yet) published analysis/summary about the issues involved. I'm
_very_ interested in the JDNC Swing extensions, sounds like lots of fun
ahead.

Best Regards,
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
rameshgupta
Offline
Joined: 2004-06-04

> Not only can the TableColumnModels be shared between
> JTables, even the TableColumns can be shared between
> TableColumnModels.
[snip]
>
> increasing the complexity screws :-) I don't
> expect that sharing a table column across unrelated
> table models can be supported in some general way -
> and now even my memory fails to come up with a historic
> use-case :-) My wish is that you don't do anything to
> prevent/hinder it.
[snip]

> Greetings
> Jeanette

If a column could be shared *between* column models, why couldn't it also be "shared" (i.e., appear multiple times) within a single column model?

If we allowed that, what would TableColumnModel.getColumnIndex(columnId) return? Multiple columns would have the same ID, but different indices in that case!

If we prevent/hinder that, why shouldn't we treat column sharing *between* column models the same way? Why do I get the sinking feeling that this was a good idea gone awry :-(

Ramesh

Kleopatra

>
> If a column could be shared *between* column models, why couldn't it also be "shared" (i.e., appear multiple times) within a single column model?
>
> If we allowed that, what would TableColumnModel.getColumnIndex(columnId) return? Multiple columns would have the same ID, but different indices in that case!
>
> If we prevent/hinder that, why shouldn't we treat column sharing *between* column models the same way?
>

A columnId should be unique per columnModel. It can't if the same column
is added more than once to a ColumnModel. If anybody is daring enough to
want it, it's her burden to handle it. So I would not bother in the
general case but assume the first found is the only one.

The same column in different models does not necessaryly break the
uniqueness requirement.

> Why do I get the sinking feeling that this was a good idea gone awry :-(

Hmm, what exactly is your problem? Leave it as is (in the "normal"
swing) and everything's fine (now that the table back-pointer is gone
and the identifer/displayValue problem solved :-)

Greetings
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Amy Fowler

Kleopatra wrote:

>>Yes, it is true that TableModel has a very vague notion of metadata,
>
>
> yeah - but now might be the chance to de-vague that a bit. How about
> introducing an extended interface TableModelEx with a formal notion of
> metadata? Plus enhancing the TableModelEvent to guarantee notification
> of metadata changes. Currently the not-supported change notification of
> column names is a real pain - most developers tend to fire a structure
> change which has very undesirerable side-effects. And is the wrong thing
> to do: it's not the structure of the table that changed, but only some
> minor aspect of one column! Even if the identifier/class of a column
> changes, it should effect _one_ column only, not the others.

Funny you bring this up -- I was just thinking about this problem last
night. We have TabularDataModel, which serves up the richer column
MetaData objects, but I don't really want to put "instance of" checks
inside JXTable to look for this concrete TableModel implementation class.
[you'd catch that ugliness in no time :-]

Your notion of an extended TableModel interface is an interesting idea....
Hum. I did consider starting with TableModel when I created the DataModel
interface. We could make DataModel extend TableModel instead of providing
wrappers that create DataModel instances out of TableModel ones.

Aim

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Kleopatra

Amy Fowler wrote:

> Funny you bring this up -- I was just thinking about this problem last
> night.

Hmm, which one - the missing metaData or the missing change notification
(in TableModel)?

> We have TabularDataModel, which serves up the richer column
> MetaData objects, but I don't really want to put "instance of" checks
> inside JXTable to look for this concrete TableModel implementation class.
> [you'd catch that ugliness in no time :-]

>
> Your notion of an extended TableModel interface is an interesting idea....
> Hum. I did consider starting with TableModel when I created the DataModel
> interface. We could make DataModel extend TableModel instead of providing
> wrappers that create DataModel instances out of TableModel ones.
>

My gut feeling would say no - I don't see a "is-a" in any direction (but
did not yet look into it as closely as you did :-)

Thinking aloud a bit: DataModel is a nice general abstraction with
key/cursor base access and a strong notion of metaData, adaptable to a
wide variety of data structures. TableModel is much more specific,
strictly 2D with index-based access with a very weak notion of metaData.
With the goal of strengthening the tableModel's metaData notion, what
about pulling out the metaData-part? Something like:

interface MetaDataProvider {
Set getFieldNames();
MetaData getMetaData(fieldName);
// need notification on add/remove/change?
// similar to ListModel?
}

interface DataModel extends MetaDataProvider {
...
}

interface TableModelExt extends TableModel, MetaDataProvider {
// plus mapping from name <--> columnIndex
}

a default implementation of MetaDataProvider could be re-used as
delegatee by most DataModel/TableModelExt implementations, the
TabularDataModelAdapter would take any TableModelExt as model and a
clever JXTable would listen to changes of the metaData independently
from changes in the data.

What do you think? Could well be that I overlooked something basic, not
having tried out any of the above :-)

Kind Regards
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Amy Fowler

Kleopatra wrote:
[snip]
>
>>We have TabularDataModel, which serves up the richer column
>>MetaData objects, but I don't really want to put "instance of" checks
>>inside JXTable to look for this concrete TableModel implementation class.
>>[you'd catch that ugliness in no time :-]
>
>
>
>
>>Your notion of an extended TableModel interface is an interesting idea....
>>Hum. I did consider starting with TableModel when I created the DataModel
>>interface. We could make DataModel extend TableModel instead of providing
>>wrappers that create DataModel instances out of TableModel ones.
>>
>
>
> My gut feeling would say no - I don't see a "is-a" in any direction (but
> did not yet look into it as closely as you did :-)
>
> Thinking aloud a bit: DataModel is a nice general abstraction with
> key/cursor base access and a strong notion of metaData, adaptable to a
> wide variety of data structures. TableModel is much more specific,
> strictly 2D with index-based access with a very weak notion of metaData.
> With the goal of strengthening the tableModel's metaData notion, what
> about pulling out the metaData-part? Something like:
>
> interface MetaDataProvider {
> Set getFieldNames();
> MetaData getMetaData(fieldName);
> // need notification on add/remove/change?
> // similar to ListModel?
> }
>
> interface DataModel extends MetaDataProvider {
> ...
> }
>
> interface TableModelExt extends TableModel, MetaDataProvider {
> // plus mapping from name <--> columnIndex
> }
>
>
> a default implementation of MetaDataProvider could be re-used as
> delegatee by most DataModel/TableModelExt implementations, the
> TabularDataModelAdapter would take any TableModelExt as model and a
> clever JXTable would listen to changes of the metaData independently
> from changes in the data.
>
> What do you think? Could well be that I overlooked something basic, not
> having tried out any of the above :-)

I like this proposal. I'll work on integrating these ideas with some
other improvements, as well as thinking about how this might fit if
we move to using Karsten's jgoodies data-binding framework, which
is on my near-term todo list.

Aim

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Kleopatra

Amy Fowler wrote:
>
> I like this proposal. I'll work on integrating these ideas with some
> other improvements, as well as thinking about how this might fit if
> we move to using Karsten's jgoodies data-binding framework, which
> is on my near-term todo list.
>

Good news - I'm a fan a JGoodies XX :-) I'm quite familiar with the
goodies binding because - besides using it in my FormBuilder/Loader - I
did a bit of code review/bug fixing for Karsten.

Currently I'm groping around at the other end: I try to find out
if/how/where both binding approaches are
similar/overlap/contact/clash/don't fit at all. Obviously I'm at the
very beginning.

Greetings
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Amy Fowler

jdnc-interest@javadesktop.org wrote:

>>I still think that's a lot of work for the developer
>>to share a TCM. Perhaps we should consider
>>simplifying this at the JNTable-level. We could build
>>a variant of JNTable that internally allocates a
>>vertical JSplitPane and two JXTables for split views.
>>This table would accept a single data model as usual,
>>and automatically share that between the two
>>JXTables. It would automatically call
>>setAutoCreateColumnsFromModel(false). It would also
>>implement TableModelListener, and automatically
>>register itself with the data model, and (get my
>>drift), automatically update the shared TCM whenever
>>there are major structural changes in the data model.
>>Did I miss anything?
>>
>>That would be a whole lot less error-prone than the
>>raw JXTable approach, don't you think?
>>
>>Ramesh
>
>
> Mark and I were just discussing what happens when a user causes a Find action to be invoked on a table inside a splitpane. How can they tell which table the JXFindDialog is associated with? See https://jdnc.dev.java.net/issues/show_bug.cgi?id=44 for his proposal, which I like quite a bit.
>
> However, when we implement split table views in JNTable, we will have one logical JNTable, but two physical JXTables inside a splitPane. What is the UI model in this case? Does a Find dialog get spawned when the user clicks in one half of the split pane before invoking the Find action, and a new one get spawned when the user clicks in the other half before invoking the Find action a second time? Is the previous one hidden in this latter case? Sounds like there should only be one Find dialog for a single JNTable even when there are separate physical parts underneath.
>
> Ramesh

This is definitely where we should consult some UI guidelines.

In the spirit of devining such a guideline from prior art, I looked at
how Excel handles this. If you split the view of the same data and
execute a find operation, it indeed invokes that operation on *both*
views, scrolling each view to bring the found item into view if necessary.
[this is actually counter to what I was expecting, which was that
only the view with input focus would change due to the find operation].

Excel's behavior seems to support Ramesh's statement about find applying
to the entire JNTable, not a single view within that table.

Aim

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Kleopatra

Hi Ramesh,

sorry for being a bit late ...

>
> We have taken care of the back reference from table column (TC) to table (T), thanks to your contributed code, and Amy should be checking in the fix soon, if she hasn't already.

Wow, you are quick ( very different from that d@&%..
bug-parade engineer who reacted today to a bug report dating from Okt.
2003 - that's a full ten months! - and suggested that I should please do
his work and check if the bug miraculously disappeared in Tiger...
)

> However, I am still grappling with some issues related to table column model (TCM) sharing.
>
> When you have shared TCMs and TCs, the relationships you mentioned above become:
>
> Each T has zero or one TCM (Unidirectional pointer from T to TCM)
> Each TCM has zero or more TC (Unidirectional pointer from TCM to TC)
> Each TCM belongs to zero or more T (No back pointer)
> Each TC belongs to zero or more TCM (No back pointer)
>

yep - except that the T has exactly one TCM.

> So, let's say T1 and T2 share a TCM. Can we then assert that T1 and T2 must share the same data model as well? Is it a developer error if they don't?

No to both, IMO. The requirement is that the data models must be
"reasonably" similar in structure/column meta data. With the very vague
notion of meta-data in TableModel - basically only the name at a certain
index - that boils down to the same number of columns and a "fitting"
name.

>
> By default, autoCreateColumnsFromModel is true. Shouldn't it be the developers' responsibility to change that to false for each T that shares a TCM with another T? Failure to do that would be a developer error, right?

Hmm, not really an error - it's only inefficient as long as the
automatically created TCM/TCs are replaced with the shared one. But I
agree that explicitly setting the autoCreate to false and move the
updating responsibility to some dedicated TableModelListener would be
the preferred approach.

>
> When T1 and T2 share the same TCM and data model, and the latter changes, both T1 and T2 get a tableChanged notification. If the TableModelEvent indicates that the entire structure of the data model has changed, it not a responsibility of T1 and T2, but of the developer to update the shared TCM once, right?

Yes. Just an aside: firing too many structure changes is eeeevil - in
that regard, TabularDataModel is not exactly an angel :-).

>
> I still think that's a lot of work for the developer to share a TCM. Perhaps we should consider simplifying this at the JNTable-level. We could build a variant of JNTable that internally allocates a vertical JSplitPane and two JXTables for split views. This table would accept a single data model as usual, and automatically share that between the two JXTables. It would automatically call setAutoCreateColumnsFromModel(false). It would also implement TableModelListener, and automatically register itself with the data model, and (get my drift), automatically update the shared TCM whenever there are major structural changes in the data model. Did I miss anything?
>
> That would be a whole lot less error-prone than the raw JXTable approach, don't you think?
>

I see nothing inherently error-prone in raw Swing/X programming only
sub-optimally educated programmers Yes, I get your drift - but I
would suggest not to define the handler inside the JNTable but formally
introduce it into the swingx layer. Then it would be usable by both
low-level developers directly and indirectly (invisibly in the
simplified api) by the JNXX layer as well.

Greetings
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rameshgupta
Offline
Joined: 2004-06-04

> > When you have shared TCMs and TCs, the
> > relationships you mentioned above become:
> >
> > Each T has zero or one TCM
> > Each TCM has zero or more TC
> > Each TCM belongs to zero or more T
> > Each TC belongs to zero or more TCM
> >
>
> yep - except that the T has exactly one TCM.

OK, counting empty TCM (in case no data/metadata was set).

>
> > So, let's say T1 and T2 share a TCM. Can we then
> > assert that T1 and T2 must share the same data model
> > as well? Is it a developer error if they don't?
>
> No to both, IMO.

Then, developers must adhere to a whole set of unwritten constraints (see below), violating any of which would still be a developer error.

> The requirement is that the data models must be
> "reasonably" similar in structure/column meta data.
> With the very vague notion of meta-data in
> TableModel - basically only the name at a
> certain index - that boils down to the
> same number of columns and a "fitting" name.
>

OK, I'm willing to approach this with an open mind :-)

The only credible use-case I have seen so far for sharing TCM is for a split view of the same logical table, and that implies shared data/metadata as well. If there is a requirement for any more generality, I would like to see a reasonable use-case :-)

Yes, it is true that TableModel has a very vague notion of metadata, which, technically, does not prevent (for example) three different tables, T1, T2, and T3, to each have their own data models M1, M2, and M3, respectively, while T1 and T2 share TCM1, and T3 has its own TCM2. Note that this does not require that TCM1 and TCM2 have the same number of columns, or that a column TC, shared between the two be in a particular location inside them.

Now, consider the implications of sharing TC between TCM1 and TCM2. In order to "fit":
(a) the shared TC must have the same model index
in M1, M2, and M3;
(b) Data in M1, M2, and M3 at that model index must be
renderable using the default renderer for the column
(in case class-specific renderer are not registered);
(c) ditto, for editors;
(d) Both TCM1 and TCM2 must return correct values from
getColumnIndexAtX(xPosition);
(e) T1, T2, and T3 must share certain view-related
properties (view column count, column margin,
column selection, selectability, column width,
resizability, header value (not identifier), ...
and I'm not sure if I've captured all the constraints!

The header value is especially vexing, because, now the metadata for M1, M2, and M3 must also agree on what the "label" for TC should be. And although it can be made to work for a synchronized splitview of a single logical table, I am not quite convinced that (d) can be implemented correctly for the fully general case (e.g., when a column has same model index, but different view index in each view).

This means somebody higher up (i.e., the app, not Swing) must have an intimate knowledge about the data, metadata, tables, column models and columns in order to make sure that these (unwritten) constraints are not violated if/when TCs and TCMs are shared.

[snip]
> >
> > I still think that's a lot of work for the
> > developer to share a TCM. Perhaps we should consider
> > simplifying this at the JNTable-level. We could build
> > a variant of JNTable that internally allocates a
> > vertical JSplitPane and two JXTables for split views.
> > This table would accept a single data model as usual,
> > and automatically share that between the two
> > JXTables. It would automatically call
> > setAutoCreateColumnsFromModel(false). It would also
> > implement TableModelListener, and automatically
> > register itself with the data model, and (get my
> > drift), automatically update the shared TCM whenever
> > there are major structural changes in the data model.
> > Did I miss anything?
> >
> > That would be a whole lot less error-prone than the
> > raw JXTable approach, don't you think?
> >
>
> I see nothing inherently error-prone in raw Swing/X
> programming only sub-optimally educated programmers...

As usual, this involves tradeoffs between flexibility and ease-of-use.

> Yes, I get your drift - but I would suggest
> not to define the handler inside the JNTable
> but formally introduce it into the swingx layer.
> Then it would be usable by both
> low-level developers directly and indirectly
> (invisibly in the simplified api) by the
> JNXX layer as well.
>
> Greetings
> Jeanette

I don't have any problem pushing the handler down into Swing/X, but I still don't see how such a handler can be made to work if the constraints that I mentioned above (and possibly others) are violated. And that's the main reason why, I think sharing TC/TCM is error-prone unless some simplifying assumptions are made.

Note that this whole discussion is moot if the app, and the app alone takes full responsibility for creating and maintaining the shared TCM/TCs, and either setting autocreateColumns to false or promptly replacing the automatically created ones with the shared ones -- although, in the last case, it will wreak havoc on column visibility control in JNTable, as it is currently implemented.

I hope we come to an agreement on this soon because this directly influences a number of existing TC/TCM-related bugs in filtering and column visibility.

Ramesh

Kleopatra

Hi Ramesh,

fun won :-)

>
> The only credible use-case I have seen so far for sharing TCM is for a split view of the same logical table, and that implies shared data/metadata as well. If there is a requirement for any more generality, I would like to see a reasonable use-case :-)

"credible" and "reasonable" is what customers want and they have lots of
imagination One use-case I remember was a view to visually compare
two sets of "similar" tabular data - f.i. an old address list vs. a
current list. That led to two tables with distinct table models but
shared TCMs for synchronized column sizing and shared BoundedRangeModels
for synchronized scrolling.

Hmm.. maybe we can say that the precondition to share a TCM across
tables with different tableModels is that the tableModels have
compatible column metadata?

>
> Yes, it is true that TableModel has a very vague notion of metadata,

yeah - but now might be the chance to de-vague that a bit. How about
introducing an extended interface TableModelEx with a formal notion of
metadata? Plus enhancing the TableModelEvent to guarantee notification
of metadata changes. Currently the not-supported change notification of
column names is a real pain - most developers tend to fire a structure
change which has very undesirerable side-effects. And is the wrong thing
to do: it's not the structure of the table that changed, but only some
minor aspect of one column! Even if the identifier/class of a column
changes, it should effect _one_ column only, not the others.

> which, technically, does not prevent (for example) three different tables, T1, T2, and T3, to each have their own data models M1, M2, and M3, respectively, while T1 and T2 share TCM1, and T3 has its own TCM2. Note that this does not require that TCM1 and TCM2 have the same number of columns, or that a column TC, shared between the two be in a particular location inside them.

>
> Now, consider the implications of sharing TC between TCM1 and TCM2. In order to "fit":

[..]

increasing the complexity screws :-) I don't expect that sharing a
table column across unrelated table models can be supported in some
general way - and now even my memory fails to come up with a historic
use-case :-) My wish is that you don't do anything to prevent/hinder it.

> >
> > > That would be a whole lot less error-prone than the
> > > raw JXTable approach, don't you think?
> > >
> >
> > I see nothing inherently error-prone in raw Swing/X
> > programming only sub-optimally educated programmers...
>
> As usual, this involves tradeoffs between flexibility and ease-of-use.

agreed - and that's where we differ slightly in our goals: personnally,
I don't want to loose any flexibility while the jdnc puts more weight
into ease-of-use. But that's not really a big hurdle, I think.

>
> I don't have any problem pushing the handler down into Swing/X, but I still don't see how such a handler can be made to work if the constraints that I mentioned above (and possibly others) are violated. And that's the main reason why, I think sharing TC/TCM is error-prone unless some simplifying assumptions are made.

agreed with emphasis on "some" simplifying - my point is that requiring
the tableModel to be the same might tend to over-simplify: requiring
them to have the same metadata is enough, IMO.

>
> Note that this whole discussion is moot if the app, and the app alone takes full responsibility for creating and maintaining the shared TCM/TCs, and either setting autocreateColumns to false or promptly replacing the automatically created ones with the shared ones -- although, in the last case, it will wreak havoc on column visibility control in JNTable, as it is currently implemented.

Ack. Hmm, I would not expect that setting the TCM would break the
visibility control ... But I didn't look too closely into JNTable, maybe
I should in my next fun break :-)

>
> I hope we come to an agreement on this soon because this directly influences a number of existing TC/TCM-related bugs in filtering and column visibility.

I'm sure we will.

Greetings
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rameshgupta
Offline
Joined: 2004-06-04

> Hi Ramesh,
>
> fun won :-)

Thanks! ;-)

>
> >
> > The only credible use-case I have seen so far for
> > sharing TCM is for a split view of the same logical
> > table, and that implies shared data/metadata as well.
> > If there is a requirement for any more generality, I
> > would like to see a reasonable use-case :-)
>
> "credible" and "reasonable" is what customers want
> and they have lots of imagination One use-case I
> remember was a view to visually compare
> two sets of "similar" tabular data - f.i. an old
> address list vs. a current list. That led to
> two tables with distinct table models but
> shared TCMs for synchronized column sizing and shared
> BoundedRangeModels for synchronized scrolling.

Wow! I certainly wouldn't have imagined that -- You win!

>
> Hmm.. maybe we can say that the precondition to share
> a TCM across tables with different tableModels is
> that the tableModels have compatible column metadata?

That oughtta work.

>
> >
> > Yes, it is true that TableModel has a very vague
> > notion of metadata,
>
> yeah - but now might be the chance to de-vague that a
> bit. How about introducing an extended interface
> TableModelEx with a formal notion of metadata?
> Plus enhancing the TableModelEvent to guarantee
> notification of metadata changes. Currently the
> not-supported change notification of column names
> is a real pain - most developers tend to fire a
> structure change which has very undesirerable
> side-effects. And is the wrong thing to do:
> it's not the structure of the table that changed,
> but only some minor aspect of one column! Even if the
> identifier/class of a column changes, it should effect
> _one_ column only, not the others.
>
Agreed. Let me think more about how we can reconcile this with our existing metadata work.

[snip]

> >
> > As usual, this involves tradeoffs between
> > flexibility and ease-of-use.
>
> agreed - and that's where we differ slightly in our
> goals: personnally, I don't want to loose any
> flexibility while the jdnc puts more weight
> into ease-of-use. But that's not really a big hurdle,
> I think.

With one foot in Swing/X and the other in JDNC-api, I can see both sides. Hopefully, the latter will make "ease-of-use" a non-issue.

>
> >
> > I don't have any problem pushing the handler down
> > into Swing/X, but I still don't see how such a
> > handler can be made to work if the constraints that I
> > mentioned above (and possibly others) are violated.
> > And that's the main reason why, I think sharing
> > TC/TCM is error-prone unless some simplifying
> > assumptions are made.
>
> agreed with emphasis on "some" simplifying - my point
> is that requiring the tableModel to be the same might
> tend to over-simplify: requiring them to have the same
> metadata is enough, IMO.

Agreed.

Ramesh

rameshgupta
Offline
Joined: 2004-06-04

> "sharing" is a concept independent of model or view.
> It's often possible in a "has-a" relationship to share the "a"
> if the coupling is carefully designed to support it, especially
> if references are uni-directional into the direction of "a" and
> if "a" is reporting changes on potentially interesting internal state.
>
> The relationships JTable --(has-a, 1:1)-->
> TableCollumnModel --(has-a, 0:*)--> TableColumn
> is such a beautiful collaboration - the back-coupling on every level
> is very loose, done via listener notification only. Not only can the
> TableColumnModels be shared between JTables, even the
> TableColumns can be shared between TableColumnModels.
> There is no burden whatever on the developer (really :-)) - but you are
> putting a hell-of-burden onto her/him if you destroy the designed
> flexibility by a back-ref from the column (all the way up the the
> highest "whole") to the table.
>

Hi Jeanette,

We have taken care of the back reference from table column (TC) to table (T), thanks to your contributed code, and Amy should be checking in the fix soon, if she hasn't already. However, I am still grappling with some issues related to table column model (TCM) sharing.

When you have shared TCMs and TCs, the relationships you mentioned above become:

Each T has zero or one TCM (Unidirectional pointer from T to TCM)
Each TCM has zero or more TC (Unidirectional pointer from TCM to TC)
Each TCM belongs to zero or more T (No back pointer)
Each TC belongs to zero or more TCM (No back pointer)

So, let's say T1 and T2 share a TCM. Can we then assert that T1 and T2 must share the same data model as well? Is it a developer error if they don't? The converse, of course, is not true. If T1 and T2 share a data model, we can not assume that they share a TCM.

By default, autoCreateColumnsFromModel is true. Shouldn't it be the developers' responsibility to change that to false for each T that shares a TCM with another T? Failure to do that would be a developer error, right?

When T1 and T2 share the same TCM and data model, and the latter changes, both T1 and T2 get a tableChanged notification. If the TableModelEvent indicates that the entire structure of the data model has changed, it not a responsibility of T1 and T2, but of the developer to update the shared TCM once, right?

I still think that's a lot of work for the developer to share a TCM. Perhaps we should consider simplifying this at the JNTable-level. We could build a variant of JNTable that internally allocates a vertical JSplitPane and two JXTables for split views. This table would accept a single data model as usual, and automatically share that between the two JXTables. It would automatically call setAutoCreateColumnsFromModel(false). It would also implement TableModelListener, and automatically register itself with the data model, and (get my drift), automatically update the shared TCM whenever there are major structural changes in the data model. Did I miss anything?

That would be a whole lot less error-prone than the raw JXTable approach, don't you think?

Ramesh

rameshgupta
Offline
Joined: 2004-06-04

> I still think that's a lot of work for the developer
> to share a TCM. Perhaps we should consider
> simplifying this at the JNTable-level. We could build
> a variant of JNTable that internally allocates a
> vertical JSplitPane and two JXTables for split views.
> This table would accept a single data model as usual,
> and automatically share that between the two
> JXTables. It would automatically call
> setAutoCreateColumnsFromModel(false). It would also
> implement TableModelListener, and automatically
> register itself with the data model, and (get my
> drift), automatically update the shared TCM whenever
> there are major structural changes in the data model.
> Did I miss anything?
>
> That would be a whole lot less error-prone than the
> raw JXTable approach, don't you think?
>
> Ramesh

Mark and I were just discussing what happens when a user causes a Find action to be invoked on a table inside a splitpane. How can they tell which table the JXFindDialog is associated with? See https://jdnc.dev.java.net/issues/show_bug.cgi?id=44 for his proposal, which I like quite a bit.

However, when we implement split table views in JNTable, we will have one logical JNTable, but two physical JXTables inside a splitPane. What is the UI model in this case? Does a Find dialog get spawned when the user clicks in one half of the split pane before invoking the Find action, and a new one get spawned when the user clicks in the other half before invoking the Find action a second time? Is the previous one hidden in this latter case? Sounds like there should only be one Find dialog for a single JNTable even when there are separate physical parts underneath.

Ramesh

Kleopatra

>
> Mark and I were just discussing what happens when a user causes a Find action to be invoked on a table inside a splitpane. How can they tell which table the JXFindDialog is associated with? See https://jdnc.dev.java.net/issues/show_bug.cgi?id=44 for his proposal, which I like quite a bit.
>
> However, when we implement split table views in JNTable, we will have one logical JNTable, but two physical JXTables inside a splitPane. What is the UI model in this case? Does a Find dialog get spawned when the user clicks in one half of the split pane before invoking the Find action, and a new one get spawned when the user clicks in the other half before invoking the Find action a second time? Is the previous one hidden in this latter case? Sounds like there should only be one Find dialog for a single JNTable even when there are separate physical parts underneath.

Hmm, how do native apps solve it?

Greetings
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rameshgupta
Offline
Joined: 2004-06-04

>> However, when we implement split table views in
>> JNTable, we will have one logical JNTable, but two
>> physical JXTables inside a splitPane. What is the UI
>> model in this case? Does a Find dialog get spawned
>> when the user clicks in one half of the split pane
>> before invoking the Find action, and a new one get
>> spawned when the user clicks in the other half before
>> invoking the Find action a second time? Is the
>> previous one hidden in this latter case? Sounds like
>> there should only be one Find dialog for a single
>> JNTable even when there are separate physical parts
>> underneath.
>
>
> Hmm, how do native apps solve it?
>
> Greetings
> Jeanette

Not sure about the Java world, but MS uses a modeless Find dialog that stays open until dismissed. The dialog automatically targets the currently active window, which might change while the dialog is displayed.

Ramesh

Kleopatra

Hi Amy,

Okay, so let's go into some details :-)

>
> TableColumn provides the getPreferredWidth() method, which is somewhat analogous to getPreferredSize() on Component.

It's tempting to overstress the analogy. The main difference as I see it
is that a Component has the responsibility to report a value calculated
on all internal state (content, insets, font...) that might influence
the result. A Component _can_ honor this responsibility because it has
all the necessary properties handy internally. A TableColumn on the
other hand, might not have access to _any_ of the properties at the
moment of a call to getPreferredWidth.

This difference is showing on how the get/setXXDim are used in client
code: while it is very rare and not at all recommended to call setXX on
a Component, it's _required_ to call on a TableColumn to get reasonable
sizing behaviour. Unfortunately there's near to no default support for
doing so.

> JTable attempts to honor this value when laying out the columns of the table in a given geometry.
>

Yes, but let's be a bit more precise: JTable reports it's own prefSize
as the sum of the pref column widths and distributes +/- space in a way
dependent on the columns' pref width if in any of the resizeModes. If
autoResize is off, JTable actually changes the preferred width of the
resizingColumn. And that's perfectly okay - to repeat myself: user prefs
rule :-) Whatever a custom TableColumn might do - it must not interfere
with the "usual" JTable behaviour (which is does if the prefWidth is
calculated in getPrefWidth). Personnally I think the TableColumn wasn't
meant to be subclassed (taking private fireXX as - concededly weak -
clue). Anyway it can't do any "self-dimensioning" because it's lacking
nearly all necessary internal state info.

>
> Other than the concern over the dependency on having the table model initialized to calculate the preferred width, I'm not sure I understand the issues you mention above. Could you elaborate further on the problem you are seeing?

hmm ... not sure if the above details made my points any clearer ...

>
> >
> > Another aspect is that there's need for something
> > much smarter which
> JTable/TableColumn already supports min, pref, and max column sizes, as well as the autoResizeMode to deal with extra or deficit space on column resizes. What additional column layout features are you looking for?

What I'm looking for is a default layouter that actually _feeds_ those
xx widths based on renderer/content/whatever :-) Should be flexible with
easy-to-use plug-in hooks for custom strategies.

> but explicit table sizing info definitely does NOT belong in the data model.

ACK. But getting a "pleasing" layout is not entirely independent of the
data model as well. I would suggest to at least have the possibility to
define layout hints (in model coordinates - "my second column always has
the title and as such should get all the excess width, if available" -
and independent of the presence of a concreate view) which can be
translated into some pixel layout when the table is realized.

>
> Personally I think it would be ashame to writeoff utilizing the metadata in configuring the display properties of the table, even if it causes some headaches for the cases where the table model/data is dynamically changing.

agreed (though I did not even look into them - JDNC has so many exciting
places :-) MetaData most probably is a good starting point for initial
layout information - though it might not be enough if content related
sizing is required.

>
> This all stemmed from the simple desire to make it very easy for developers to customize rendering properties on a per-column basis without having to spend a bunch of time understanding the cell rendering mechanism -- probably something which is more applicable to JNTable, rather than JXTable, and I'm not happy with the current design, though not necessarily for the same reasons you cite above.

I see the forces ... however, they should not lead to misbehaviour on
the pure swing layer.

> Though you are the first developer I've heard mention utilizing the sharing of column models!

maybe you never met any hard-cord JTable enthusiasts :-) It's quite
common when two tables' column resizing need to be in synch, f.i if one
is showing all data and the other a filtered set or f.i. when having
"frozen rows". An example for a not so common context are "frozen
columns" by filtering a common columnModel into the header/content
tables.

>
>
> We considered using the cell highlighting mechanism to achieve the per-column cell property customization, but as Ramesh mentioned, we were concerned (perhaps prematurely) that it would impose a performance penalty to be doing so much lookup/setting on a per-cell basis.

If you did not measure the impact it was premature - my opinion, of
course :-) But don't get me wrong, please: I'm not at all convinced that
there is _no_ penalty - historically the perceived table repainting
performance improved drastically by optimizing the renderer and the
number of accesses to the renderers (by ToolTipManager f.i.). So I
understand your concern perfectly well - nevertheless it should not
influence the design too much in this early stage, IMO.

> I am VERY interested.

fine - did you my mail?

Greetings
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rameshgupta
Offline
Joined: 2004-06-04

> > but explicit table sizing info definitely does NOT
> belong in the data model.
>
> ACK. But getting a "pleasing" layout is not entirely
> independent of the
> data model as well. I would suggest to at least have
> the possibility to
> define layout hints (in model coordinates - "my
> second column always has
> the title and as such should get all the excess
> width, if available" -
> and independent of the presence of a concreate view)
> which can be
> translated into some pixel layout when the table is
> realized.

Agree. This makes sense in the Swing Extensions layer.

> > Though you are the first developer I've heard
> mention utilizing the sharing of column models!
>
> maybe you never met any hard-cord JTable
> enthusiasts :-) It's quite
> common when two tables' column resizing need to be in
> synch, f.i if one
> is showing all data and the other a filtered set or
> f.i. when having
> "frozen rows". An example for a not so common context
> are "frozen
> columns" by filtering a common columnModel into the
> header/content
> tables.
>
This is a perfectly legitimate use-case. Also, requests for frozen rows/columns/panes are very popular.

Ramesh

Anonymous

Hi Jeanette -

Ramesh has addressed many of your questions, but I wanted to comment on a number of issues you pointed out. As you have discovered, we've been playing around with a variety of approaches to certain problems and there are design glitches for sure.

>
> 1) getting some responsibility to provide reasonable
> widths
>
> A quote from getPrefWidth(..): "// .. do we want to
> calculate every
> time?" - my answer to this is a clear "no" and going
> further even a
> clear "never".
>
> One reason is that the "pref" is a "preference"
> controlled by context:
> one is the preference as a component might return in
> prefSize, the other
> is the preference a user does express by resizing the
> column. The
> TableColumn cannot decide which is meant, currently
> it assumes to be the
> first kind of pref which makes is not-resizable with
> a prototype and the
> table in autoresizeoff mode.

TableColumn provides the getPreferredWidth() method, which is somewhat analogous to getPreferredSize() on Component. JTable attempts to honor this value when laying out the columns of the table in a given geometry.

Frequently it is desirable to be able to specify this preferred width in terms of a prototype value rather than in pure pixels because it's difficult to predict how much space a renderer will actually need (fonts, decorators, etc). Thus, we added the "prototypeValue" property on our TableColumnExt class. It's just a way to specify the preferred width in terms of a value rather than hard pixels, but you are correct in that it needs info from the model to properly process that value.

Other than the concern over the dependency on having the table model initialized to calculate the preferred width, I'm not sure I understand the issues you mention above. Could you elaborate further on the problem you are seeing?

>
> Another aspect is that there's need for something
> much smarter which
> includes min/max sizes and resizing behaviour of the
> columns as well -
> some means to really "layout" the columns. All size
> requirements might
> depend on the TableModel. Too much burden for a
> simple data-storing
> class, I think. Any effort to make it "smarter" will
> introduce
> additional coupling into realms it should not have
> any knowledge of.

JTable/TableColumn already supports min, pref, and max column sizes, as well as the autoResizeMode to deal with extra or deficit space on column resizes. What additional column layout features are you looking for?

The meta-data for a table model might be able to provide info which is useful in determining the ideal size of a cell (e.g. RowSetMetaData has the "columnDisplaySize" property), but explicit table sizing info definitely does NOT belong in the data model.

Personally I think it would be ashame to writeoff utilizing the metadata in configuring the display properties of the table, even if it causes some headaches for the cases where the table model/data is dynamically changing.

>
> Yet another reason is that binding any
> tableModel-related "layout-info"
> into a TableColumn is possible only after the table
> is filled with some
> data and is lost whenever the model changes. That's
> at least annoying
> though not un-resolvable.

Yes - we discovered that this causes trickiness with timing of certain operations, but I think we can resolve it.

> 2) taking control about the renderers to use
>
> Until now JTable has full control about choosing the
> renderers. The
> implemented strategy is to ask the column first which
> gives clients an
> emergency hook - in my experience setting a renderer
> on the tableColumn
> is rare event (most unliked because they are lost on
> model changes) and
> used as a last resort, f.i. if choosing the renderer
> by column class is
> not fine-grained enough. So the main route of
> choosing is through the
> JTable's mapping of default renderes to column class.
>
> TableColumnEx snatches that control from JTable if
> labelProperties are
> applied, it insists on returning a renderer of its
> _own_ choosing if
> none is set in the column. Tssss ...
>

This all stemmed from the simple desire to make it very easy for developers to customize rendering properties on a per-column basis without having to spend a bunch of time understanding the cell rendering mechanism -- probably something which is more applicable to JNTable, rather than JXTable, and I'm not happy with the current design, though not necessarily for the same reasons you cite above.

I'll spin up a separate thread for this discussion because it's a fairly deep topic when you get into it.

>
> 3) back-referencing into JTable makes me feel very
> uneasy.
>
> It's a necessity if the TableColumn is burdened with
> its new tasks.
> Nevertheless it "smells" strongly on a general level,
> introducing a very
> strong coupling somewhere hidden in the bowels. As a
> consequence,
> ColumnModels are no longer shareable across tables.
> Which is a
> showstopper in certain contexts (a lot of mine at
> least).

100% agreed. I'd hoped we'd figure out how to remove this hack before we opened up the source, but the wart remains. Though you are the first developer I've heard mention utilizing the sharing of column models!

> A lot of nagging - I know, but have seen it all, have
> been exactly there
> half a year ago :-) - IMO moving those enhanced
> responsibilities into
> the TableColumn is a dead end. An alternative is to
> move it out into a
> dedicated handler which can be easily configured by
> client code at any
> time and is used by the table (or some adapter) when
> it comes to
> actually configuring the renderers/columns.
> Currently I'm tweaking
> JXTable to use my approach - and it looks promising
> :-)

We considered using the cell highlighting mechanism to achieve the per-column cell property customization, but as Ramesh mentioned, we were concerned (perhaps prematurely) that it would impose a performance penalty to be doing so much lookup/setting on a per-cell basis.

We'll look forward to hearing about your proposed approach.

>
> Amy, if you are interested, please pass me a note: I
> can mail you a link
> to a not (yet) published analysis/summary about the
> issues involved. I'm
> _very_ interested in the JDNC Swing extensions,
> sounds like lots of fun
> ahead.

I am VERY interested. You've clearly got table wisdom to impart as we move this component forward.

Aim

rameshgupta
Offline
Joined: 2004-06-04

[snip]
> > Another aspect is that there's need for something
> > much smarter which
> > includes min/max sizes and resizing behaviour of
> > the columns as well -
> > some means to really "layout" the columns. All
> > size requirements might
> > depend on the TableModel. Too much burden for a
> > simple data-storing
> > class, I think. Any effort to make it "smarter"
> > will introduce additional coupling into realms it should not have
> > any knowledge of.
>
[snip]
>
> The meta-data for a table model might be able to
> provide info which is useful in determining the ideal
> size of a cell (e.g. RowSetMetaData has the
> "columnDisplaySize" property), but explicit table
> sizing info definitely does NOT belong in the data
> model.
>

The "columnDisplaySize" property of RowSetMetaData sets the designated column's normal maximum width in characters, not pixel values. This should not affect the pixel width of a column, I think. Pixel width of a column should be set based on explicit values for column width, or calculated from min, max, preferred width, or from the prototype value for a cell -- all of which are view properties, not model properties. Right?

[snip]
> >
> > 3) back-referencing into JTable makes me feel very
> > uneasy.
> >
> > It's a necessity if the TableColumn is burdened with
> > its new tasks.
> > Nevertheless it "smells" strongly on a general level,
> > introducing a very
> > strong coupling somewhere hidden in the bowels.
> > As a consequence,
> > ColumnModels are no longer shareable across tables.
> > Which is a
> > showstopper in certain contexts (a lot of mine at
> > least).
>
> 100% agreed. I'd hoped we'd figure out how to remove
> this hack before we opened up the source, but the
> wart remains. Though you are the first developer
> I've heard mention utilizing the sharing of column
> models!
>

Yes, I agree. A column model is part of the view information, not part of the data model. Generally, only parts of the data model are shared between views. Sharing parts of a view across views, while possible, can become tricky, with the management burden falling on developers. However, we should look into the column model sharing issue just so we don't preclude developers from taking on this burden if they choose to.

[snip]

Kleopatra

Hi Ramesh,

>
> The "columnDisplaySize" property of RowSetMetaData sets the designated column's normal maximum width in characters, not pixel values. This should not affect the pixel width of a column, I think. Pixel width of a column should be set based on explicit values for column width, or calculated from min, max, preferred width, or from the prototype value for a cell -- all of which are view properties, not model properties. Right?

Yes and no. Yes - the _calculated_ pixel values are view properties. No
- the necessary _input_ to do some reasonable calculation may be
model-dependent, as well on metadata as on content.

> >
> > 100% agreed. I'd hoped we'd figure out how to remove
> > this hack before we opened up the source, but the
> > wart remains. Though you are the first developer
> > I've heard mention utilizing the sharing of column
> > models!
> >
>
> Yes, I agree. A column model is part of the view information, not part of the data model. Generally, only parts of the data model are shared between views. Sharing parts of a view across views, while possible, can become tricky, with the management burden falling on developers. However, we should look into the column model sharing issue just so we don't preclude developers from taking on this burden if they choose to.

Please allow me to strongly disagree: "sharing" is a concept independent
of model or view. It's often possible in a "has-a" relationship to share
the "a" if the coupling is carefully designed to support it, especially
if references are uni-directional into the direction of "a" and if "a"
is reporting changes on potentially interesting internal state.

The relationships JTable --(has-a, 1:1)--> TableCollumnModel --(has-a,
0:*)--> TableColumn is such a beautiful collaboration - the
back-coupling on every level is very loose, done via listener
notification only. Not only can the TableColumnModels be shared between
JTables, even the TableColumns can be shared between TableColumnModels.
There is no burden whatever on the developer (really :-) - but you are
putting a hell-of-burden onto her/him if you destroy the designed
flexibility by a back-ref from the column (all the way up the the
highest "whole") to the table.

Furthermore, I would like to take a slightly different viewpoint than a
rock-hard "columnModel is part of the view - nothing else". Mind - I
don't question the validity of this, only want to inject a variating
line of thought :-)

Basically, a TableColumn can be viewed as something similar to a
BoundedRangeModel customized for easy use in a JTable context - its core
responsibility (the only responsibility besides firing propertyChanges
on state changes) is to guarantee min <= width, pref <= max. Seeing this
similarity may lead to using it in a similar way - namely, feeding the
xxWidth values into it "from the outside" instead of letting the
TableColumn calculate them itself (which it can't in a reasonable way
without destroying the design - oops, I'm repeating myself ) Slots
for storing names/renderers/editors now are a mere add-ons.

On a similar track, TableColumnModel can be viewed as a collection (of
tableColumns), which enhances the "usual" collenction operations
(storage/add/remove/..) with the responsibility to notify listeners on
those modification (adding/removing/re-ordering). Here the
more-view-related add-on is the selection.

At least keeping the non-view (core - but that's arguable :) aspects in
the back of the mind widens developers' perspectives (talking about me
:) which sometimes helps to find solutions to tricky problems.

Okay, sermon is over let's go to work.

Greetings
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rameshgupta
Offline
Joined: 2004-06-04

> > The "columnDisplaySize" property of RowSetMetaData
> > sets the designated column's normal maximum width in
> > characters, not pixel values. This should not affect
> > the pixel width of a column, I think. Pixel width of
> > a column should be set based on explicit values for
> > column width, or calculated from min, max, preferred
> > width, or from the prototype value for a cell -- all
> > of which are view properties, not model properties.
> > Right?
>
> Yes and no. Yes - the _calculated_ pixel values are
> view properties. No
> - the necessary _input_ to do some reasonable
> calculation may be
> model-dependent, as well on metadata as on content.

If the _necessary_ input is model-dependent, as well as on metadata and content, then we need to reconcile this with the requirements for asynchronous data loading in tables. Doesn't this preclude laying out the columns until everything has been loaded? Is there a reasonable middle ground that we can take?

>
> > >
> > > 100% agreed. I'd hoped we'd figure out how to
> remove
> > > this hack before we opened up the source, but the
> > > wart remains. Though you are the first developer
> > > I've heard mention utilizing the sharing of
> column
> > > models!
> > >
> >
> > Yes, I agree. A column model is part of the view
> information, not part of the data model. Generally,
> only parts of the data model are shared between
> views. Sharing parts of a view across views, while
> possible, can become tricky, with the management
> burden falling on developers. However, we should look
> into the column model sharing issue just so we don't
> preclude developers from taking on this burden if
> they choose to.
>
> Please allow me to strongly disagree: "sharing" is a
> concept independent
> of model or view. It's often possible in a "has-a"
> relationship to share
> the "a" if the coupling is carefully designed to
> support it, especially
> if references are uni-directional into the direction
> of "a" and if "a"
> is reporting changes on potentially interesting
> internal state.

I have always thought of table columns as extremeties of a single body. An octopus *has* eight tentacles, but none of those are shared with another octopus. Even tables that share the same data model have separate columns and column models.

This is true by default, unless one calls table.setAutoCreateColumnsFromModel(false); And a call to this method is an implicit assertion that the developer takes the responsibility to manage the column model, rather than letting JTable take care of it automatically.

Also, the amount of work a developer has to do can grow depending on the timing of this call relative to the time that a table's model is set. For highly dynamic models, the developer also has to figure out if or when they need to throw out their column information and recreate it. This also has implications on column visibility support in JNTable.

Having said that, I still agree with many of the points you make, specifically about the back reference from column to table, and as Amy said, we do want to clean that up. The frozen rows feature, and synchronized resizing of columns in a split view are legitimate use-cases that we hadn't taken into consideration when we added the back reference to the table.

>
> The relationships JTable --(has-a, 1:1)-->
> TableCollumnModel --(has-a,
> 0:*)--> TableColumn is such a beautiful collaboration
> - the
> back-coupling on every level is very loose, done via
> listener
> notification only. Not only can the TableColumnModels
> be shared between
> JTables, even the TableColumns can be shared between
> TableColumnModels.
> There is no burden whatever on the developer (really
> :-)

OK, so burden is too strong a word :-) But sharing columns this way doesn't come automatically, even when one calls table.setAutoCreateColumnsFromModel(false);

> - but you are
> putting a hell-of-burden onto her/him if you destroy
> the designed
> flexibility by a back-ref from the column (all the
> way up the the
> highest "whole") to the table.

Agreed :-) and we want to fix that.

>
> Furthermore, I would like to take a slightly
> different viewpoint than a
> rock-hard "columnModel is part of the view - nothing
> else". Mind - I
> don't question the validity of this, only want to
> inject a variating
> line of thought :-)

We have to remember that TableColumnModel is an interface, and nothing in that interface sanctions the kind of usage we are discussing here. If you look at TableColumnModel.getColumnIndexAtX(int xPosition), all you can assume is that column model is part of the view. Anything beyond that, and you are counting on being lucky (as with DefaultTableColumnModel), no?

From TableColumn documentation:
"Some implementations may assume that all TableColumnModels are unique, therefore we would recommend that the same TableColumn instance not be added more than once to a TableColumnModel. To show TableColumns with the same column of data from the model, create a new instance with the same modelIndex."

Ramesh

Kleopatra

jdnc-interest@javadesktop.org wrote:
>
> If the _necessary_ input is model-dependent, as well as on metadata and content, then we need to reconcile this with the requirements for asynchronous data loading in tables. Doesn't this preclude laying out the columns until everything has been loaded? Is there a reasonable middle ground that we can take?

Good point. A possible way out might be to wait for the first chunk of
content to come in - that's what I'm currently doing. Often the layout
widths need not be very precise measurements, at least not initially. If
the table comes up with a good (as visually perceived) approximation -
f.i. by measuring the content of the first n lines plus some user action
to "expand a column until the content isn't truncated" once all content
is loaded (in win that#s done by double clicking into the resize region
of a column) users are happy - mostly

> I have always thought of table columns as extremeties of a single body. An octopus *has* eight tentacles, but none of those are shared with another octopus. Even tables that share the same data model have separate columns and column models.

interesting picture :-)

>
> This is true by default, unless one calls table.setAutoCreateColumnsFromModel(false); And a call to this method is an implicit assertion that the developer takes the responsibility to manage the column model, rather than letting JTable take care of it automatically.

agreed. And don't let us forget another path by which developers take
control, that is by explicitly setting the tableColumnModel.

> > - but you are
> > putting a hell-of-burden onto her/him if you destroy
> > the designed
> > flexibility by a back-ref from the column (all the
> > way up the the
> > highest "whole") to the table.
>
> Agreed :-) and we want to fix that.
>

Fine :-) Did you already have a look at the code I attached yesterday?

> > Furthermore, I would like to take a slightly
> > different viewpoint than a
> > rock-hard "columnModel is part of the view - nothing
> > else". Mind - I
> > don't question the validity of this, only want to
> > inject a variating
> > line of thought :-)
>
> We have to remember that TableColumnModel is an interface, and nothing in that interface sanctions the kind of usage we are discussing here.

neither does it prohibit it, exhaustive as it is:

"public interface TableColumnModel

Defines the requirements for a table column model object suitable for
use with JTable".

> If you look at TableColumnModel.getColumnIndexAtX(int xPosition), all you can assume is that column model is part of the view. Anything beyond that, and you are counting on being lucky (as with DefaultTableColumnModel), no?

Never used that ... But reading the doc, to me it seems to strengthen my
arguments of a) a TableColumnModel is designed to be a "model" and as
such sharable and b) that a TableColumnModel is primarily designed to be
an ordered collection of TableColumns with some virtual horizontal
(combined) range:

"Returns the index of the column that lies on the horizontal point,
xPosition. [...] In keeping with Swing's separable model architecture, a
TableColumnModel does not know how the table columns actually appear on
screen. [..] Because the model does not know how the columns are laid
out on screen, the given xPosition should not be considered to be a
coordinate in 2D graphics space. Instead, it should be considered to be
a width from the start of the first column in the model."

>
> >From TableColumn documentation:
> "Some implementations may assume that all TableColumnModels are unique, therefore we would recommend that the same TableColumn instance not be added more than once to a TableColumnModel. To show TableColumns with the same column of data from the model, create a new instance with the same modelIndex."

Yeah - that comment was introduced in the 1.4 release. I could never
figure out why this note was deemed to be necessary, especially in the
light of the above getColumnIndexAtX api doc. Any ideas? Or any examples
where a TableColumnModel implementation relies on a uniquely owned
TableColumn?

Ramesh, please don't mind my stubbornness, I just like to clear an
argument until the very end. And I'll do my best to help finding
solutions to the problems I raise ;-).

Greetings
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rameshgupta
Offline
Joined: 2004-06-04

[snip]
> > > Furthermore, I would like to take a slightly
> > > different viewpoint than a
> > > rock-hard "columnModel is part of the view -
> > > nothing else". Mind - I
> > > don't question the validity of this, only want to
> > > inject a variating line of thought :-)
> >
> > We have to remember that TableColumnModel is an
> > interface, and nothing in that interface sanctions
> > the kind of usage we are discussing here.
>
> neither does it prohibit it...
>
> > If you look at
> > TableColumnModel.getColumnIndexAtX(int xPosition),
> > all you can assume is that column model is part of
> > the view. Anything beyond that, and you are counting
> > on being lucky (as with DefaultTableColumnModel), no?
>
> Never used that ... But reading the doc, to me it
> seems to strengthen my
> arguments of a) a TableColumnModel is designed to be
> a "model" and as
> such sharable and b) that a TableColumnModel is
> primarily designed to be
> an ordered collection of TableColumns with some
> virtual horizontal
> (combined) range:
> [snip]
>

That was just one example. I could cite more, e.g., getColumnMargin(), getColumnSelectionAllowed(), ... These are necessarily view-related properties, which I don't think should be usurped by a "model" in the MVC sense. For example, how is one supposed to implement getColumnSelectionAllowed() for a sharable TableColumnModel between a read-write view that allows column selection, and a read-only view that does not?

> >
> > From TableColumn documentation:
> > "Some implementations may assume that all
> > TableColumnModels are unique, therefore we would
> > recommend that the same TableColumn instance not be
> > added more than once to a TableColumnModel. To show
> > TableColumns with the same column of data from the
> > model, create a new instance with the same
> > modelIndex."
>
> Yeah - that comment was introduced in the 1.4
> release. I could never
> figure out why this note was deemed to be necessary,
> especially in the
> light of the above getColumnIndexAtX api doc. Any
> ideas? Or any examples
> where a TableColumnModel implementation relies on a
> uniquely owned
> TableColumn?
>
> Ramesh, please don't mind my stubbornness, I just
> like to clear an argument until the very end.
> And I'll do my best to help finding
> solutions to the problems I raise ;-).
>
> Greetings
> Jeanette

I have no doubt in my mind that you are helping us find the best solutions. Also, I think of this more as a discussion than as an argument. I also admire your resolve (not stubbornness :-)) because nothing would be worse than just caving in, especially when you have objective reasons to support your point.

To recap the high-order bits:

1. We do understand that a back reference from a table column to a table is a bad thing, and we will fix it (Haven't looked at your code yet, though).

2. TableColumnModel was probably envisioned to be used as a "model" in the MVC sense, but even the JavaDocs acknowledge that some implementations might be running afoul of that vision. Although the specs do not prohibit TableColumnModel sharing, they do not guarantee that either. But we will take a more flexible approach and try to make it work for the use-cases that you brought up.

3. We are not "rock hard" inflexible :-), and we do welcome serious discussion on topics.

Ramesh

Amy Fowler

Hi Jeanette -

Could you please send that attachment again -- I'm unable to get it from
the forum and the email version seems to have vanished.

thanks!
Aim

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rameshgupta
Offline
Joined: 2004-06-04

Hi Jeanette,

This is a very fair and level-headed criticism of some of the column-related functionality in JXTable. As you said, the code is still raw, and there is a window of opportunity to take corrective action before the functionality in JXTable and the support classes are rolled into Swing proper. For this, we do look forward to constructive feedback such as yours.

>
> Being a JTable freak the first place I went was the
> JXTable - very nice,
> all those decorations :-) It looks like being the
> most mature of the
> "collection views" (list, tree, combo), those will
> eventually be Searchable as well?

Thanks for your kind words :-) Searchability is implemented by hooking *any* user-defined UI into either the filtering or the highlighting mechanism, depending on what you want to accomplish. Basically, one defines a pattern filter or a pattern highlighter, and attaches it to a table, and *optionally* to a separate UI, such as a search panel, to interactively change the search parameters (pattern, case-sensitivity, etc.). The JSearchPanel class is a rudimentary example of such an optional UI.

Neither JSearchPanel, nor PatternFilter and PatternHighlighter are directly coupled to JXTable. JSearchPanel was also kept out of JNTable, but we can revisit that based on the feedback we get. The bottom line is that all of the components that support filtering and highlighting will (eventually) support searching in this manner.

>
> I would like to comment on some design/implementation
> issues - though
> I'm aware that the code is still raw, I view that
> more as a chance than
> a obstacle. Basically they relate to TableColumnEx
> and its enhanced
> responsibilities.
>
>
> 1) getting some responsibility to provide reasonable
> widths
>
> A quote from getPrefWidth(..): "// .. do we want to
> calculate every
> time?" - my answer to this is a clear "no" and going
> further even a
> clear "never".
>
> One reason is that the "pref" is a "preference"
> controlled by context:
> one is the preference as a component might return in
> prefSize, the other
> is the preference a user does express by resizing the
> column. The
> TableColumn cannot decide which is meant, currently
> it assumes to be the
> first kind of pref which makes is not-resizable with
> a prototype and the
> table in autoresizeoff mode.
>

Good point. What should happen when the table bound changes? Should the preferred size hint be ignored after the user has resized the column, but autoresize mode is on? I think, the most reliable way to make a column not resizable is to set its max width and min width to the same value.

> Another aspect is that there's need for something
> much smarter which
> includes min/max sizes and resizing behaviour of the
> columns as well -
> some means to really "layout" the columns. All size
> requirements might
> depend on the TableModel. Too much burden for a
> simple data-storing
> class, I think. Any effort to make it "smarter" will
> introduce
> additional coupling into realms it should not have
> any knowledge of.
>
> Yet another reason is that binding any
> tableModel-related "layout-info"
> into a TableColumn is possible only after the table
> is filled with some
> data and is lost whenever the model changes. That's
> at least annoying
> though not un-resolvable.
>

Yes, layout always brings in its own set of complexities, and we've deliberately tried to keep things simple in the early access release. Moving forward, we have to address this issue, not just for column layout, but also for layout of elements within a form, and so on. Please do help us with your insight into this process.

>
> 2) taking control about the renderers to use
>
> Until now JTable has full control about choosing the
> renderers. The
> implemented strategy is to ask the column first which
> gives clients an
> emergency hook - in my experience setting a renderer
> on the tableColumn
> is rare event (most unliked because they are lost on
> model changes) and
> used as a last resort, f.i. if choosing the renderer
> by column class is
> not fine-grained enough. So the main route of
> choosing is through the
> JTable's mapping of default renderes to column class.
>
> TableColumnEx snatches that control from JTable if
> labelProperties are
> applied, it insists on returning a renderer of its

> _own_ choosing if
> none is set in the column. Tssss ...
>

The main justification for this was to enhance performance by setting the renderer properties once per column, rather than once for every row within the column. We'd be happy to consider alternative proposals on this :-)

Kleopatra

Hi Ramesh,

>
> Neither JSearchPanel, nor PatternFilter and PatternHighlighter are directly coupled to JXTable. JSearchPanel was also kept out of JNTable, but we can revisit that based on the feedback we get. The bottom line is that all of the components that support filtering and highlighting will (eventually) support searching in this manner.
>

Thanks for explaining. Looks very sound and flexible, I already love it
:-) The "eventually" is what I half-guessed, seeing the find-action and
-dialog in the JXTable.

>
> Good point. What should happen when the table bound changes? Should the preferred size hint be ignored after the user has resized the column, but autoresize mode is on?

Good question. User preferences are holy .

>
> Yes, layout always brings in its own set of complexities, and we've deliberately tried to keep things simple in the early access release. Moving forward, we have to address this issue, not just for column layout, but also for layout of elements within a form, and so on. Please do help us with your insight into this process.

I'll stay tuned.

>
> The main justification for this was to enhance performance by setting the renderer properties once per column, rather than once for every row within the column. We'd be happy to consider alternative proposals on this :-)

Hmm, did you experience any performance problems? My main (yet unsolved)
problem when "applying" LabelProperties to renderers shared across
columns is that I could not "un-apply" them. Need to experiment a bit
more.

Greetings
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rameshgupta
Offline
Joined: 2004-06-04

>> The main justification for this was to enhance
>> performance by setting the renderer properties once
>> per column, rather than once for every row within the
>> column. We'd be happy to consider alternative
>> proposals on this :-)
>
> Hmm, did you experience any performance problems?

No, but, intuitively, this seemed like a good idea :-)
In fact, the highlighting mechanism performs per-cell prep on renderers with excellent performance characteristics.

> My main (yet unsolved) problem when "applying" LabelProperties to
> renderers shared across columns is that I could not "un-apply" them.
> Need to experiment a bit more.

How are you trying to unapply properties? The way it works is you create a LabelProperties instance and set some properties, say background, font, and icon on it, and finally apply the properties. To unapply only the font, but leave the rest as-is, just create a new LabelProperties instance, set the font property on the new Labelproperties to the old value, and apply the properties. Since you set only the font property, only that will be changed.

Kleopatra

> >
> > Hmm, did you experience any performance problems?
>
> No, but, intuitively, this seemed like a good idea :-)

I'm in the habit of ranting against "assumed" perfomance issues :-)

> In fact, the highlighting mechanism performs per-cell prep on renderers with excellent performance characteristics.
>

yeah, that's my experience as well: in my own system I'm doing some
"post-prepare" configuration of renderers (and editors, btw, we don't
want to have them jumping alignments when starting edits) without
performance penalties.

> > My main (yet unsolved) problem when "applying" LabelProperties to
> > renderers shared across columns is that I could not "un-apply" them.
> > Need to experiment a bit more.
>
> How are you trying to unapply properties? The way it works is you create a LabelProperties instance and set some properties, say background, font, and icon on it, and finally apply the properties. To unapply only the font, but leave the rest as-is, just create a new LabelProperties instance, set the font property on the new Labelproperties to the old value, and apply the properties. Since you set only the font property, only that will be changed.

Thanks, that's working :-) Should have been more careful in trying to
explain what I'm doing.

The requirements are:
a) TableColumns are not allowed to enforce a renderer per column, that
is generally cellRenderer in the column itself is null and
b) if a labelProperty is not set, the renderer should show with the
default as defined by the renderer itself.

The problem comes if the same renderer instance is shared between a
column which sets a property and a column which does nothing - then the
renderer has the properties of the first column in the second as well
because there is no way to "reset to renderer default". In my
environment I only had to support alignment so I walked around it by
requiring all renderers to set the alignment internally on every
getComponent() (just as they do with background/foreground f.i.).

Having known the problem, I did assume that it was the ultimate reason
for you making the TableColumn request a new instance of an appropriate
renderer instead of asking the table for the default, too much guessing
around :-)

Hmm, thinking about it: a renderer which sets any of the applied props
internally does
overrule the column's setting anyway, not sure if that's intentional?

Another point I'm not sure of is how much backwards compatibility is on
your agenda. My expectation would be to simply change the type in custom
component factories from JTable to JXTable and then get sorting/finding
for free without any other changes anywhere in my code. If that's a goal
JXTable must not make any assumptions about the concrete type of
TableColumn - it's very usual to have table.autocreateColumns at false
to do custom creation/configuration of columns. Currently it does by
exposing (and unconditionally typecasting) columns to TableColumnEx. I
would suggest to treat the type as an implementation detail and expose
the functionality instead of the type - and make any jdnc classes use
the functionality:

class JXTable ...

public void applyCellProperties(LabelProperties cp, int col)

private TableColumnExt getTableColumnExt(int col)

Some quirk I stumbled about:

// Note: it's critical to create the new columns before
// deleting the old ones. Why?
int modelColumnCount = model.getColumnCount();

Assuming that it happens with TabularDataModel (more guess work -
because you have a unit- test for it, and I had the same problem in a
custom column factory) and leads to creating all columns twice: might be
a threading problem connected with the side-effect of getColumnCount
(which loads the meta-data). Then structureChanged is fired twice and
the second time createColumns is called adds them to the first. Did not
debug into it too deeply, though - now I make sure to load the metadata
first before setting the model to the table. The issue should be solved
cleanly, I think.

Greetings
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rameshgupta
Offline
Joined: 2004-06-04

Thanks for stating your requirements on table columns, cell renderers, and label properties. We need to rethink how best to reconcile our design to your needs.

>
> Another point I'm not sure of is how much backwards
> compatibility is on your agenda.

In the near term, JXTable is intended to be a drop-in replacement for JTable. Longer term, the functionality in JXTable is expected to migrate to JTable itself.

> My expectation would be to simply change
> the type in custom component factories from JTable to JXTable
> and then get sorting/finding for free without any other changes
> anywhere in my code.

That's a goal, but as you've pointed out, we haven't reached that compatibility goal yet :-)

> If that's a goal
> JXTable must not make any assumptions about the
> concrete type of
> TableColumn - it's very usual to have
> table.autocreateColumns at false
> to do custom creation/configuration of columns.
> Currently it does by
> exposing (and unconditionally typecasting) columns to
> TableColumnEx. I
> would suggest to treat the type as an implementation
> detail and expose
> the functionality instead of the type - and make any
> jdnc classes use
> the functionality:
>
> class JXTable ...
>
> public void applyCellProperties(LabelProperties cp,
> p, int col)
>
> private TableColumnExt getTableColumnExt(int col)
>

This is a reasonable suggestion. Perhaps you can help us implement/test this, and submit a patch? Not too much to ask, I hope :-)

>
> Some quirk I stumbled about:
>
> // Note: it's critical to create the new columns
> s before
> // deleting the old ones. Why?
> int modelColumnCount = model.getColumnCount();
>
> Assuming that it happens with TabularDataModel (more
> guess work -
> because you have a unit- test for it, and I had the
> same problem in a
> custom column factory) and leads to creating all
> columns twice: might be
> a threading problem connected with the side-effect of
> getColumnCount
> (which loads the meta-data). Then structureChanged is
> fired twice and
> the second time createColumns is called adds them to
> the first. Did not
> debug into it too deeply, though - now I make sure to
> load the metadata
> first before setting the model to the table. The
> issue should be solved
> cleanly, I think.
>
>
>
> Greetings
> Jeanette

Oh, so that's what's going on with duplicate columns! We noticed this problem occasionally, but the problem couldn't be reproduced reliably. Thanks for shining the spotlight on this one!

Ramesh

Jeanette Winzenburg

Hi Ramesh,

>
> That's a goal, but as you've pointed out, we haven't reached that compatibility goal yet :-)

I'm impatient.

>
> This is a reasonable suggestion. Perhaps you can help us implement/test this, and submit a patch? Not too much to ask, I hope :-)

hmm ... I'm very reluctant to show experimental code ... but I will
because I think it's easier to discuss issues on a changed code basis.

So I attach a zip (is it possible on this discussion list? I'll see in a
minute :) with strategic changes - it's an extract of my "exploring"
code with some c&p from custom classes in my context. I think it will
compile in the swingx layer but might require changes in the other jdnc
layers (not many as far as direct invocation is concerned but I did
nothing to check the mark-up level).

My main goal was a proof-of-concept that and how it's possible to get
rid of the TableColumnExt back ref into JTable. With slight changes
(namely explicitly triggering table.layoutColumns() after setting
cellProperties) the JXTableUnitTest behaves as the original - except for
the yet unsolved problem when sharing renderers across columns
(Testcase[14]). As a plus, tableColumns are resizable by users, even if
cellprops are set.

No guarantee and nowhere near clean nor complete code - anyway, I'm
eagerly awaiting any feedback, ma�ana

Greetings
Jeanette
[jdnc20jul2004.zip]
---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net