alpha version, October 2000
The real work is performed by the conversion object. The CXCConversion class is the only one you must subclass to make your own filter; even the CXCFilter class can be in simple cases used without subclassing.
There are three property variables of the CXCConversion class quite interesting for us:
{
CXCGeneralData *_input,*_output;
CXCProgress *_progress;
}
The _input and _output contain the input and output data, represented by CXCGeneralData objects. The _progress is a link to a user interface, and is described in the CXCProgress class description.
The conversion object is made by a filter (see the CXCFilter class), and then it is automatically sent the following messages in the following order:
Naturally, in case a particular implementation does not need the begin, prepare, or finish methods, they need not be reimplemented. The only one method which must be reimplemented is the doConvert one. The default implementation of the details method returns nil; therefore you need to reimplement it only in case you need some detailed dialogue.
(*) the array contains both the description of the data to be shown in the dialogue, and the feedback to get the values set by user in the conversion object. The particular mechanism is described in the CXDialog class.
In case you use the details dialogue, you might want to reimplement the validateDetails method as well. It facilitates two tasks: primarily, you can decode the values from the detail dialogue, if needed. Then, you can possibly inform the framework that the values are not proper, and that the user must change them.
Unless your code retains the _input and _output data for some reason, they will be both deleted in the standard destructor. Note that deleting the output data automatically commits all changes; thus you don't need to concern with commiting or saving the data yourself.
The input data object is fully initialized from the very beginning (ie. at the time the CXCFilter's conversionFor method gets called by the framework). Though, the output data can be initialized only partially: whilst the _input variable can be used from the beginning, the _output one might not be valid before the CXCConversion's prepare method! The reason is that the framework code might want to postpone the creation of the output file (or buffer or whatever) till the details are set. Note: currently there is no CXCFilter API to postpone the output data creation this way; it is under construction, and will be provided by future versions.
When the doConvert method ends normally, the framework presumes the conversion finished successfully. Therefore, in case you need to abort the conversion, just generate an exception. So as to report the reason of the abortion to the user, generate an exception of name "XCConversionAbortedException", with the string to be shown as the exception reason. The exception name is defined as a macro XCConversionAbortedException.
In case the conversion was aborted, the partial unfinished output data (including any supplementary streams, see the CXCStreamData class) are removed automatically. You need the aborted method only for any non-standard resources you use outside of the scope of the output CXC*Data object.
+CXCConversion *conversionWith(CXCGeneralData *input,CXCFilter *cFilter);
The conversionWith constructor should be used in the filter code to make a conversion, in case you reimplement the conversionFor method. If you do so, just use this (ie. the filter) for the cFilter argument. The input data must be made by that time, and given as the first constructor argument. The output data can be prepared and set using the setOutput method as well, or that can be postponed just before the prepare method is called. Note: currently there is no CXCFilter API to postpone the output data creation this way; it is under construction, and will be provided by future versions.
See the CXCFilter class for the general pattern of making the conversion.
-CXCGeneralData *output;
-void setOutput(CXCGeneralData *output);
The setOutput method is used in the filter code to set the output data. Since the CXCConversion's property are not accessible from there, and accessor ouptut is provided for the improbable case you might need to check the current value.
See the CXCFilter class for the general pattern of making the conversion.
-CXCFilter *currentFilter;
The currentFilter method can be used to access the filter which made the current conversion. It might be needed, say, to get the current filter name to be written out into some comment in the output data.
Often the filter is needed for the services it offers, like its filterDefaults or globalDefaults methods.
-void begin;
Any initialization can be done here, without need to reimplement the init method.
-CXArray *details;
In case this method returns a non-nil, the return value is presumed to be an array of CXDialog objects, which describe a details dialogue (ie. a dialogue, via which the user sets the conversion details--like which delimiter to use in a textual spreadsheet export). In case it returns a nil (or is not reimplemented at all), no details dialogue will be shown.
The returned array can have the first object of the CXString class. If so, the string will be used as the dialogue title, and the dialogue contents will be constructed using all the remaining items (of class CXDDI).
-id validateDetails;
After the details dialogue (if any) is closed, this method gets called. In case it returns nil, the values entered via the details dialogue are considered to be valid. In case it returns a CXString, it will be shown as the InfoPrint, and the details dialogue will remain on the screen; thus, the returned string should contain a hint for the user which valuse is to be corrected (and how to do so).
The method can return also an array (of CXDialog objects) which specifies a dialogue the very same way the details return value does. If so, the new dialogue is opened over the details dialogue as a nested one. After it is closed, the validateDetails method will be called again.
This way a more detailed or better explaining dialogue can be presented in case the plain info print (ensured by the string return value) is not sufficient.
-void detailLineChanged(CXString *dialLabel,CXString *pageLabel,CXString *label,int line,id value,XDialogueAccess *access);
Sometimes, a dynamic access to the details dialogue (or any nested subdialogue, created by returning an array from the validateDetails method) might be needed: for example, you might want to dynamically show or hide a dialogue line as a result of value, selected on other line.
This method is automatically called whenever a labelled line (see the CXDialog class) value inside the details dialogue (or any nested subdialogue) is changed. The label and line arguments specify the line which was changed: the line is just the line number in the current details dialogue or nested subdialogue, whilst the label distinguishes exactly the CXDialog item, which is represented by the line.
The value is the new value, just set on the line. Non-object values (indexes for the index lists or Boolean values) are represented by an object created using the XNUM2OBJ standard macro.
Finally, the access is an accessor object for the dialogue items: it allows any other dialogue item to be accessed and appropriately changed. The services of the XDialogueAccess protocol (in C++-speak, an abstract class; in Epoc-speak, a mixin) are described in the CXDialog class.
-void prepare;
Called just before the conversion starts. The _output property is fully initialized now; it could have been not in all the previous methods.
-void doConvert;
Perform the conversion here. The _input property should be read in, the _output property should be written out, and the _progress property should be used to report the progress (see the appropriate classes).
In case a serious problem occurs which does not allow to complete the conversion, just raise an exception--the conversion will be aborted automatically (and, the finish and aborted methods will get called).
-void finish;
This method is called after the conversion has ended (regardless it was normally or via an exception). Place here any code needed to release resources.
-void aborted;
This method gets called only in case the conversion was aborted. Place here any cleanup of a non-standard partially prepared output data (the standard output data, accessed thru the _output property, will be removed automatically).
Copyright © 1999-2000 X.soft, all rights reserved