//======================================================================== // // Form.h // // Copyright 2006 Julien Rebetez // //======================================================================== #ifndef FORM_H #define FORM_H #ifdef USE_GCC_PRAGMAS #pragma interface #endif #include "Object.h" #include "goo/GooVector.h" class GooString; class Array; class Dict; class Annot; class Catalog; enum FormFieldType { formButton, formText, formChoice, formSignature, formUndef, }; enum FormButtonType { formButtonCheck, formButtonPush, formButtonRadio }; class Form; class FormField; class FormFieldButton; class FormFieldText; class FormFieldSignature; class FormFieldChoice; //------------------------------------------------------------------------ // FormWidget // A FormWidget represents the graphical part of a field and is "attached" // to a page. //------------------------------------------------------------------------ class FormWidget { public: virtual ~FormWidget(); // see the description of FormField::LoadChildrenDefaults virtual void loadDefaults () {} // Check if point is inside the field bounding rect GBool inRect(double x, double y) { return x1 <= x && x <= x2 && y1 <= y && y <= y2; } // Get the field bounding rect void getRect(double *xa1, double *ya1, double *xa2, double *ya2) { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; } unsigned getID () { return ID; } void setID (unsigned int i) { ID=i; } FormField *getField () { return field; } FormFieldType getType() { return type; } Object* getObj() { return &obj; } Ref getRef() { return ref; } void setChildNum (unsigned i) { childNum = i; } unsigned getChildNum () { return childNum; } void setFontSize(double f) { fontSize = f; } double getFontSize () { return fontSize; } GBool isModified () { return modified; } bool isReadOnly() const; // return the unique ID corresponding to pageNum/fieldNum static int encodeID (unsigned pageNum, unsigned fieldNum); // decode id and retrieve pageNum and fieldNum static void decodeID (unsigned id, unsigned* pageNum, unsigned* fieldNum); protected: FormWidget(XRef *xrefA, Object *aobj, unsigned num, Ref aref, FormField *fieldA); FormWidget(FormWidget *dest); void updateField (const char *key, Object *value); FormField* field; FormFieldType type; Object obj; Ref ref; XRef *xref; GBool defaultsLoaded; GBool modified; //index of this field in the parent's child list unsigned childNum; /* Field ID is an (unsigned) integer, calculated as follow : the first sizeof/2 bits are the field number, relative to the page the last sizeof/2 bits are the page number [page number | field number] (encoding) id = (pageNum << 4*sizeof(unsigned)) + fieldNum; (decoding) pageNum = id >> 4*sizeof(unsigned); fieldNum = (id << 4*sizeof(unsigned)) >> 4*sizeof(unsigned); */ unsigned ID; double x1, y1; // lower left corner double x2, y2; // upper right corner double fontSize; //font size if this widget has text }; //------------------------------------------------------------------------ // FormWidgetButton //------------------------------------------------------------------------ class FormWidgetButton: public FormWidget { public: FormWidgetButton(XRef *xrefA, Object *dict, unsigned num, Ref ref, FormField *p); ~FormWidgetButton (); FormButtonType getButtonType() const; void setState (GBool state, GBool calledByParent=gFalse); GBool getState (); char* getOnStr () { return onStr->getCString(); } void loadDefaults(); void setNumSiblingsID (int i); void setSiblingsID (int i, unsigned id) { siblingsID[i] = id; } //For radio buttons, return the IDs of the other radio buttons in the same group unsigned* getSiblingsID () const { return siblingsID; } int getNumSiblingsID () const { return numSiblingsID; } protected: unsigned* siblingsID; // IDs of dependent buttons (each button of a radio field has all the others buttons // of the same field in this array) int numSiblingsID; GooString *onStr; FormFieldButton *parent; GBool state; }; //------------------------------------------------------------------------ // FormWidgetText //------------------------------------------------------------------------ class FormWidgetText: public FormWidget { public: FormWidgetText(XRef *xrefA, Object *dict, unsigned num, Ref ref, FormField *p); //return the field's content (UTF16BE) GooString* getContent() ; //return a copy of the field's content (UTF16BE) GooString* getContentCopy(); //except a UTF16BE string void setContent(GooString* new_content); void loadDefaults (); bool isMultiline () const; bool isPassword () const; bool isFileSelect () const; bool noSpellCheck () const; bool noScroll () const; bool isComb () const; bool isRichText () const; int getMaxLen () const; protected: FormFieldText *parent; }; //------------------------------------------------------------------------ // FormWidgetChoice //------------------------------------------------------------------------ class FormWidgetChoice: public FormWidget { public: FormWidgetChoice(XRef *xrefA, Object *dict, unsigned num, Ref ref, FormField *p); ~FormWidgetChoice(); void loadDefaults (); int getNumChoices(); //return the display name of the i-th choice (UTF16BE) GooString* getChoice(int i); //select the i-th choice void select (int i); //toggle selection of the i-th choice void toggle (int i); //deselect everything void deselectAll (); //except a UTF16BE string //only work for editable combo box, set the user-entered text as the current choice void setEditChoice(GooString* new_content); GooString* getEditChoice (); bool isSelected (int i); bool isCombo () const; bool hasEdit () const; bool isMultiSelect () const; bool noSpellCheck () const; bool commitOnSelChange () const; bool isListBox () const; protected: void _updateV (); bool _checkRange (int i); FormFieldChoice *parent; }; //------------------------------------------------------------------------ // FormWidgetSignature //------------------------------------------------------------------------ class FormWidgetSignature: public FormWidget { public: FormWidgetSignature(XRef *xrefA, Object *dict, unsigned num, Ref ref, FormField *p); protected: FormFieldSignature *parent; }; //------------------------------------------------------------------------ // FormField // A FormField implements the logical side of a field and is "attached" to // the Catalog. This is an internal class and client applications should // only interact with FormWidgets. //------------------------------------------------------------------------ class FormField { public: FormField(XRef* xrefa, Object *aobj, const Ref& aref, FormFieldType t=formUndef); virtual ~FormField(); // Accessors. FormFieldType getType() { return type; } Object* getObj() { return &obj; } Ref getRef() { return ref; } void setReadOnly (bool b) { readOnly = b; } bool isReadOnly () const { return readOnly; } FormWidget* findWidgetByRef (Ref aref); // Since while loading their defaults, children may call parents methods, it's better // to do that when parents are completly constructed void loadChildrenDefaults(); // only implemented in FormFieldButton virtual void fillChildrenSiblingsID (); protected: void _createWidget (Object *obj, Ref aref); FormFieldType type; // field type Ref ref; bool terminal; Object obj; XRef *xref; FormField **children; int numChildren; FormWidget **widgets; bool readOnly; private: FormField() {} }; //------------------------------------------------------------------------ // FormFieldButton //------------------------------------------------------------------------ class FormFieldButton: public FormField { public: FormFieldButton(XRef *xrefA, Object *dict, const Ref& ref); FormButtonType getButtonType () { return btype; } bool noToggleToOff () const { return noAllOff; } // returns gTrue if the state modification is accepted GBool setState (int num, GBool s); void fillChildrenSiblingsID (); virtual ~FormFieldButton(); protected: FormButtonType btype; int size; int active_child; //only used for combo box bool noAllOff; }; //------------------------------------------------------------------------ // FormFieldText //------------------------------------------------------------------------ class FormFieldText: public FormField { public: FormFieldText(XRef *xrefA, Object *dict, const Ref& ref); GooString* getContent () { return content; } GooString* getContentCopy (); void setContentCopy (GooString* new_content); virtual ~FormFieldText(); bool isMultiline () const { return multiline; } bool isPassword () const { return password; } bool isFileSelect () const { return fileSelect; } bool noSpellCheck () const { return doNotSpellCheck; } bool noScroll () const { return doNotScroll; } bool isComb () const { return comb; } bool isRichText () const { return richText; } int getMaxLen () const { return maxLen; } protected: GooString* content; bool multiline; bool password; bool fileSelect; bool doNotSpellCheck; bool doNotScroll; bool comb; bool richText; int maxLen; }; //------------------------------------------------------------------------ // FormFieldChoice //------------------------------------------------------------------------ class FormFieldChoice: public FormField { public: FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref); virtual ~FormFieldChoice(); int getNumChoices() { return numChoices; } GooString* getChoice(int i) { return choices[i].optionName; } GooString* getExportVal (int i) { return choices[i].exportVal; } //select the i-th choice void select (int i); //toggle selection of the i-th choice void toggle (int i); //deselect everything void deselectAll (); //only work for editable combo box, set the user-entered text as the current choice void setEditChoice(GooString* new_content); GooString* getEditChoice (); bool isSelected (int i) { return choices[i].selected; } int getNumSelected (); bool isCombo () const { return combo; } bool hasEdit () const { return edit; } bool isMultiSelect () const { return multiselect; } bool noSpellCheck () const { return doNotSpellCheck; } bool commitOnSelChange () const { return doCommitOnSelChange; } bool isListBox () const { return !combo; } /* these functions _must_ only be used by FormWidgetChoice */ void _setNumChoices (int i) { numChoices = i; } void _createChoicesTab (); void _setChoiceExportVal (int i, GooString* str) { choices[i].exportVal = str; } void _setChoiceOptionName (int i, GooString* str) { choices[i].optionName = str; } protected: bool combo; bool edit; bool multiselect; bool doNotSpellCheck; bool doCommitOnSelChange; struct ChoiceOpt { GooString* exportVal; //the export value ("internal" name) GooString* optionName; //displayed name bool selected; //if this choice is selected }; int numChoices; ChoiceOpt* choices; GooString* editedChoice; }; //------------------------------------------------------------------------ // FormFieldSignature //------------------------------------------------------------------------ class FormFieldSignature: public FormField { public: FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref); virtual ~FormFieldSignature(); }; //------------------------------------------------------------------------ // Form // This class handle the document-wide part of Form (things in the acroForm // Catalog entry). //------------------------------------------------------------------------ class Form { public: Form(XRef *xrefA, Object* acroForm); ~Form(); // Look up an inheritable field dictionary entry. static Object *fieldLookup(Dict *field, char *key, Object *obj); /* Creates a new Field of the type specified in obj's dict. used in Form::Form and FormField::FormField */ static FormField *createFieldFromDict (Object* obj, XRef *xref, const Ref& aref); Object *getObj () const { return acroForm; } GBool getNeedAppearances () const { return needAppearances; } int getNumFields() const { return numFields; } FormField* getRootField(int i) const { return rootFields[i]; } FormWidget* findWidgetByRef (Ref aref); void postWidgetsLoad(); private: FormField** rootFields; int numFields; int size; XRef* xref; Object *acroForm; GBool needAppearances; }; //------------------------------------------------------------------------ // FormPageWidgets //------------------------------------------------------------------------ class FormPageWidgets { public: FormPageWidgets (XRef *xrefA, Object* annots, unsigned int page, Form *form); ~FormPageWidgets(); int getNumWidgets() const { return numWidgets; } FormWidget* getWidget(int i) const { return widgets[i]; } private: FormWidget** widgets; int numWidgets; int size; unsigned pageNum; XRef* xref; }; #endif