]> Shamusworld >> Repos - architektonas/blobdiff - src/fileio.cpp
Added object pane, grouping, load/save functionality.
[architektonas] / src / fileio.cpp
index e0028cd90228c9d96a6ecd0fddea57f11382183f..1002dca87fecf22b79cbb2883253e9660fe6c34b 100644 (file)
@@ -108,42 +108,53 @@ OTHER CONSIDERATIONS:
 
 */
 
-enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFLine, OTFCircle, OTFArc,
-       OTFDimension, OTFPolygon, OTFText, OTFImage, OTFBlock, OTFEndOfFile };
+//enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFLine, OTFCircle, OTFArc,
+//     OTFDimension, OTFPolygon, OTFText, OTFImage, OTFBlock, OTFEndOfFile };
+enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
 
 
-/*static*/ bool FileIO::SaveAtnsFile(FILE * file, Container * object)
+// Instantiate class variables
+/*static*/ int FileIO::objectFileType = OTFObject;
+
+
+/*static*/ bool FileIO::SaveAtnsFile(FILE * file, Container * c)
 {
-       /* Approach: loop through the container, doing a depth-first traversal. Any extra
-          containers found are looped through until there aren't any more down, then
-          ordinary objects are described. This can be handled by a virtual Object function
-          that reports the object by itself if it's a non-Container, otherwise it
-          enumerates all objects within itself. */
+       /* Approach: loop through the container, doing a depth-first traversal. Any
+          extra containers found are looped through until there aren't any more
+          down, then ordinary objects are described. This can be handled by a
+          virtual Object function that reports the object by itself if it's a non-
+          Container, otherwise it enumerates all objects within itself. */
 
-       fprintf(file, "ARCHITEKTONAS DRAWING V1.0\n");
+       fprintf(file, "ARCHITEKTONAS DRAWING V1.1\n");
 #if 0
        object->Enumerate(file);
-       fprintf(file, "END\n");
-       return true;
 #else
-       return false;
+       WriteObjectToFile(file, (Object *)c);
 #endif
+       fprintf(file, "END\n");
+       return true;
 }
 
 
 /*static*/ bool FileIO::LoadAtnsFile(FILE * file, Container * drawing)
 {
-//     char buffer[256];
        float version;
 
        fscanf(file, "ARCHITEKTONAS DRAWING V%f", &version);
 
 //printf("Load: version = %f\n", version);
-       if (version != 1.0)
-               return false;
-       /* Approach: read each object in the file, one by one. If the object is a Container,
-          add objects to it until an "endContainer" marker is found. This will require a
-          stack to maintain the current Container. */
+//     if (version != 1.0)
+//             return false;
+
+       if (version == 1.0)
+               return LoadVersion1_0(file, drawing);
+       else if (version == 1.1)
+               return LoadVersion1_1(file, drawing);
+
+       return false;
+       /* Approach: read each object in the file, one by one. If the object is a
+          Container, add objects to it until an "endContainer" marker is found.
+          This will require a stack to maintain the current Container. */
 
 #if 0
        std::vector<Container *> containerStack;
@@ -158,9 +169,10 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFLine, OTFCircle, OTFArc,
                        return false;
 
                // object->type down below can be replaced with objType.
-               // Above could be: bool FileIO::GetObjectFromFile(FILE *, Object *, ObjectType *);
-               // where the return value tells if it's a valid object, Object * returns the
-               // reconstructed object and ObjectType * returns the object type.
+               // Above could be: bool FileIO::GetObjectFromFile(FILE *, Object *,
+               // ObjectType *); where the return value tells if it's a valid object,
+               // Object * returns the reconstructed object and ObjectType * returns
+               // the object type.
 
                if (objectType == OTFEndOfFile)
                {
@@ -193,21 +205,114 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFLine, OTFCircle, OTFArc,
 }
 
 
-/*static*/ bool FileIO::GetObjectFromFile(FILE * file, Object * parent, Object ** object, int * objectType)
+/*static*/ bool FileIO::LoadVersion1_0(FILE * file, Container * drawing)
+{
+       // Approach: read each object in the file, one by one. If the object is a
+       // Container, add objects to it until an "endContainer" marker is found.
+       // This will require a stack to maintain the current Container.
+       std::vector<Container *> containerStack;
+       Container * currentTopContainer = drawing;
+
+       while (!feof(file))
+       {
+               // Reconstruct the object
+               Object * obj = GetObjectFromFile(file);
+
+               // objectFileType is set in GetObjectFromFile()...
+               if (objectFileType == OTFObject)
+               {
+                       if (obj == NULL)
+                               return false;
+
+                       currentTopContainer->objects.push_back(obj);
+//printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.size(), currentTopContainer->objects.size());
+
+                       // If the object is a container, push current TLC on the stack and
+                       // set it as the new TLC
+                       if (obj->type == OTContainer)
+                       {
+                               containerStack.push_back(currentTopContainer);
+                               currentTopContainer = (Container *)obj;
+                       }
+               }
+               else if (objectFileType == OTFContainerEnd)
+               {
+                       // Container is done, so pop the stack to get back the previous TLC
+                       currentTopContainer = containerStack.back();
+                       containerStack.pop_back();
+               }
+               else if (objectFileType == OTFEndOfFile)
+               {
+//printf("Load: container size = %li\n", drawing->objects.size());
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+/*static*/ bool FileIO::LoadVersion1_1(FILE * file, Container * drawing)
+{
+       // Approach: read each object in the file, one by one. If the object is a
+       // Container, add objects to it until an "endContainer" marker is found.
+       // This will require a stack to maintain the current Container.
+       std::vector<Container *> containerStack;
+       Container * currentTopContainer = drawing;
+
+       while (!feof(file))
+       {
+               // Reconstruct the object (extended format!)
+               Object * obj = GetObjectFromFile(file, true);
+
+               // objectFileType is set in GetObjectFromFile()...
+               if (objectFileType == OTFObject)
+               {
+                       if (obj == NULL)
+                               return false;
+
+                       currentTopContainer->objects.push_back(obj);
+//printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.size(), currentTopContainer->objects.size());
+
+                       // If the object is a container, push current TLC on the stack and
+                       // set it as the new TLC
+                       if (obj->type == OTContainer)
+                       {
+                               containerStack.push_back(currentTopContainer);
+                               currentTopContainer = (Container *)obj;
+                       }
+               }
+               else if (objectFileType == OTFContainerEnd)
+               {
+                       // Container is done, so pop the stack to get back the previous TLC
+                       currentTopContainer = containerStack.back();
+                       containerStack.pop_back();
+               }
+               else if (objectFileType == OTFEndOfFile)
+               {
+//printf("Load: container size = %li\n", drawing->objects.size());
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+/*static*/ Object * FileIO::GetObjectFromFile(FILE * file, bool extended/*= false*/)
 {
-#if 0
        char buffer[256];
        int foundLayer = 0;
-       int num = fscanf(file, "%s", buffer);
-       bool recognized = false;
-       *object = NULL;
+       /*int num =*/ fscanf(file, "%s", buffer);
+       Object * obj = NULL;
+       objectFileType = OTFObject;
 //printf("FileIO: fscanf returned %i, buffer = \"%s\"\n", num, buffer);
 
 // The following fugliness is for troubleshooting. Can remove later.
        if ((strcmp(buffer, "END") != 0) && (strcmp(buffer, "ENDCONTAINER") != 0))
 {
 errno = 0;
-               num = fscanf(file, " %i ", &foundLayer);
+               /*num =*/ fscanf(file, " %i ", &foundLayer);
 //printf("FileIO: fscanf returned %i, foundLayer = %i\n", num, foundLayer);
 if (errno)
 {
@@ -230,65 +335,116 @@ if (errno)
 }
 }
 
+       // Need to add pen attributes as well... do that for v1.1 :-P
        if (strcmp(buffer, "LINE") == 0)
        {
-//printf("      Found LINE.\n");
-               recognized = true;
-               Vector v1, v2;
-               fscanf(file, "(%lf,%lf) (%lf,%lf)", &v1.x, &v1.y, &v2.x, &v2.y);
-//printf("      Number of params recognized: %i\n", n);
-               *object = new Line(v1, v2, parent);
-               *objectType = OTFLine;
+               Point p1, p2;
+               fscanf(file, "(%lf,%lf) (%lf,%lf)", &p1.x, &p1.y, &p2.x, &p2.y);
+               obj = (Object *)new Line(p1, p2);
        }
        else if (strcmp(buffer, "CIRCLE") == 0)
        {
-               recognized = true;
-               Vector v;
+               Point p;
                double r;
-               fscanf(file, "(%lf,%lf) %lf", &v.x, &v.y, &r);
-               *object = new Circle(v, r, parent);
-               *objectType = OTFCircle;
+               fscanf(file, "(%lf,%lf) %lf", &p.x, &p.y, &r);
+               obj = (Object *)new Circle(p, r);
        }
        else if (strcmp(buffer, "ARC") == 0)
        {
-               recognized = true;
-               Vector v;
+               Point p;
                double r, a1, a2;
-               fscanf(file, "(%lf,%lf) %lf, %lf, %lf", &v.x, &v.y, &r, &a1, &a2);
-               *object = new Arc(v, r, a1, a2, parent);
-               *objectType = OTFArc;
+               fscanf(file, "(%lf,%lf) %lf, %lf, %lf", &p.x, &p.y, &r, &a1, &a2);
+               obj = (Object *)new Arc(p, r, a1, a2);
        }
        else if (strcmp(buffer, "DIMENSION") == 0)
        {
-               recognized = true;
-               Vector v1, v2;
+               Point p1, p2;
                DimensionType type;
-               fscanf(file, "(%lf,%lf) (%lf,%lf) %i", &v1.x, &v1.y, &v2.x, &v2.y, &type);
-               *object = new Dimension(v1, v2, type, parent);
-               *objectType = OTFDimension;
+               fscanf(file, "(%lf,%lf) (%lf,%lf) %i", &p1.x, &p1.y, &p2.x, &p2.y, (int *)&type);
+               obj = (Object *)new Dimension(p1, p2, type);
        }
        else if (strcmp(buffer, "CONTAINER") == 0)
        {
-               recognized = true;
-               *objectType = OTFContainer;
+               obj = (Object *)new Container();
+//             objectFileType = OTFContainer;
        }
        else if (strcmp(buffer, "ENDCONTAINER") == 0)
        {
-               recognized = true;
-               *objectType = OTFContainerEnd;
+               objectFileType = OTFContainerEnd;
        }
        else if (strcmp(buffer, "END") == 0)
        {
-               recognized = true;
-               *objectType = OTFEndOfFile;
+               objectFileType = OTFEndOfFile;
        }
 
-       if (*object)
-               (*object)->layer = foundLayer;
+       if (obj != NULL)
+       {
+               obj->layer = foundLayer;
 
-       return recognized;
-#else
-       return false;
-#endif
+               if (extended && (obj->type != OTContainer))
+               {
+                       fscanf(file, " (%i, %f, %i)", &obj->color, &obj->thickness, &obj->style);
+               }
+       }
+
+       return obj;
+}
+
+
+/*static*/ bool FileIO::WriteObjectToFile(FILE * file, Object * obj)
+{
+       // Sanity check
+       if (obj == NULL)
+               return false;
+
+       switch (obj->type)
+       {
+       case OTLine:
+               fprintf(file, "LINE %i (%lf,%lf) (%lf,%lf)", obj->layer, obj->p[0].x, obj->p[0].y, obj->p[1].x, obj->p[1].y);
+               break;
+       case OTCircle:
+               fprintf(file, "CIRCLE %i (%lf,%lf) %lf", obj->layer, obj->p[0].x, obj->p[0].y, obj->radius[0]);
+               break;
+       case OTEllipse:
+               break;
+       case OTArc:
+               fprintf(file, "ARC %i (%lf,%lf) %lf, %lf, %lf", obj->layer, obj->p[0].x, obj->p[0].y, obj->radius[0], obj->angle[0], obj->angle[1]);
+               break;
+       case OTPolygon:
+               break;
+       case OTDimension:
+//             fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i\n", layer, position.x, position.y, endpoint.x, endpoint.y, dimensionType);
+               fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i", obj->layer, obj->p[0].x, obj->p[0].y, obj->p[1].x, obj->p[1].y, ((Dimension *)obj)->subtype);
+               break;
+       case OTSpline:
+               break;
+       case OTText:
+               fprintf(file, "TEXT %i (%lf,%lf) \"%s\"", obj->layer, obj->p[0].x, obj->p[0].y, ((Text *)obj)->s.c_str());
+               break;
+       case OTContainer:
+       {
+               Container * c = (Container *)obj;
+
+               if (c->topLevel == false)
+                       fprintf(file, "CONTAINER %i\n", obj->layer);
+
+               std::vector<void *>::iterator i;
+
+               for(i=c->objects.begin(); i!=c->objects.end(); i++)
+                       WriteObjectToFile(file, (Object *)*i);
+
+               if (c->topLevel == false)
+                       fprintf(file, "ENDCONTAINER\n");
+
+               break;
+       }
+       default:
+               break;
+       }
+
+       if (obj->type != OTContainer)
+               fprintf(file, " (%i, %f, %i)\n", obj->color, obj->thickness, obj->style);
+
+       return true;
 }