[Tibor Vyletel]
>Hello Fopsters,
I use FOP (dev 1.0) in a bit different scenario as you. My renderer works in GEF framework. Till now, I have hacked simple change in relevant layout managers:
BlockLayoutManager.getParentArea(Area childArea) { ... // this creates connection between fobj and curBlockArea: curBlockArea.addTrait(Trait.ID_AREA, this.fobj); ... }
This solution is just a hack and a maintainance nightmare, as the design is constantly changing ;)
I am aware that described construction is breaking memory optimization goals, however I need it to achieve my goal: enable editing after the rendering process and make this editing as responsive as possible.
Lately (in fact, after the removal of getID() method from FObj), I've been thinking about more elegant solution which would allow me to track a mapping between FObjs and Areas in cases I need it. I know that any technique which would force this connection in standard processing would not be possible, because its effects on memory consumption would be relevant.
My alternative idea is: - create AreaFactory interface (or abstract class) which would be responsible for creation of areas. Provide default implementating class with today's functionality scattered among LMs. There are to choices how to design this interface: a) with one strong method: Area createArea(LayoutManager lm, FObj fobj, Object constraints) b) with a set of specialized methods for creation of different area types: Inline createInline(...) {} Block createBlock(...) {} ...
Would you need to return subclasses of Inline and Block etc? Or would you just set various additional traits such as this.fobj?
- refactor instantiation of area objects in layout managers: remove all direct instantiations and replace them with calls to DefaultAreaFactory - solve how to configure AreaFactory before layouting process. Layout managers don't have access to UserAgent so far, so the best method would probably be a pair of static methods:
Actually, LMs normally has access to the fobj and through that the FONode.getUserAgent() method.
AreaFactory AreaFactory.getFactory() AreaFactory.setFactory(AreaFactory factory) and this constructrion in LMs: currArea = AreaFactory().getFactory().create....
When this pattern would be applied, my problem would be simply solved by creation of descendants for some Area classes, which would hold reference to the FObj data. Default implementation would bring no extra memory consumption and/or relevant speed degradation.
The reason why I have written this mail, is to obtain some feedback about
suggested refactoring. In fact I am forced to do some changes to the FOP
code because of my project's special requirements.
Would you still need to change FOP sources, even after your proposal was implemented?
The real payback for me would the case when all the maintainance nightmares would be gone and this can happen only when creation of Areas is more modular. I think that modularization of this could bring its two cents to the quality of the FOP's source code.
From your description I sort of get the impression that a smaller change, such having all LMs call a new method, say
AbstractLayoutManager.setGeneralTraits(FObj)
which has a default empty implementation. Would it be good enough for you to change AbstractLayoutManager to add your special requirements?
regards, finn