/***************************************************************************

 * Description: nodeops.cc:482-808  - 041012.2355 nodeops041012r1.cc in COOL-BDE\04sbde

 *      node_resize performs the node resize operation.  It does

 *      this based on the button event and other variables passed

 *      in to it.  All code within this function was lifted from

 *      the button*.cc files ... BUTTON_MOVED action calls doresize;

 * Revised - RJL 041007-13 - refactoring for state model clarity

 *     TBD: Restore xor GC in doresize to erase as well as redraw during motion

 * Error handling:

 *      NONE.

 * Side effects:

 *      NONE.

 ***************************************************************************/

void node_resize ( XButtonEvent *event,

                  int state, /* Canvas State (eventually just NodeCreate)*/

                  node_attributes *attribute, /* circle, square, etc. */

                  int button_op) /* BUTTON_UP, BUTTON_DOWN,BUTTON_MOVED */

{

    float sx, sy;

    static hcg_key id; // static added - RJL041012

    char curr_shape[20];

    float center_x, center_y, radius;

    float temp_x, temp_y, temp_radius;

    float diff_x, diff_y;

    double squares;

    static int first_time = 0;  //RJL041012

    static graphobject *selected_node = NULL;

    //static int NResize = 0;   // Resize ---> NResize ---> Reconfirmed- RJL041010

    static int Reconfirmed = 0; // new flag to  discrim SResize_Node action at button_up

                        // TBD: split state SNode_Resize, replacing Reconfirmed

    DCtoWC(event->x, event->y, &sx, &sy);

    switch (state)

    {

        case SResize:

            Reconfirmed = 0;

            first_time = 0;

            switch (button_op) {

                    case BUTTON_DOWN_EVENT:

                        unselect(); //graphobject::unselect(){selected=0;highlight(0)}

                        selection(canvas, (int)sx, (int)sy);

                        break;  // wait for button Up

 

                    case BUTTON_MOVED_EVENT: // wait for button_up and reconfirm

                        break;

 

                    case  BUTTON_UP_EVENT: //moved action from case BUTTON_DOWN-041010

                        // added getid() and hasType(id,HN) - RJL041010

                        if (currentselection == 0)  {

                                break;

                        }

                        else { // (currentselection != 0)

                            id = (hcg_key)currentselection->getid();

                            if (!hasType(id, HN)) { // a type  HN was selected

                                unselect();

                                currentselection = 0;

                                displayMessage(

                                    "Invalid selection; select Node to Resize\n");

                            }

                            else {

                                selected_node = currentselection; // save obj*

                                HNcurr = (struct HN*)currentselection->getcurr();

                                selected.changeAttribState(SResize_node);

                                changeCanvasCursor(movehand); // from arrow;

                            }

                            break;

                        }  // end case BUTTON_UP

                    default:

                        PostErrorMsg(SResize);

                        break;

              }  // end switch(button_op)

            break;  // end case SResize;

 

        case SResize_node:

            switch (button_op) {

                case BUTTON_DOWN_EVENT:

                    //assert(selected_node != 0 && hasType(id.HN));

                    unselect();  //graphobject::unselect(){selected=0;highlight(0)}

                    selection(canvas, (int)sx, (int)sy); // could be NULL

 

                    if(currentselection == 0){  // invalid graphobject* - no selection;

                        selected_node = 0;

                        changeCanvasCursor(arrow);

                        unselect();

                        displayMessage("No object selected; try again\n");

                        selected.changeAttribState(SResize); //to wait for BUTTON_UP

                        break;    // reenter SResize for BUTTON_UP action

                   }

                   else { // (currentselection != 0)

                        id = (hcg_key) currentselection->getid();

                        fprintf(stderr, "SResize_node: id = 0x%lx\n", id);

                        if (!hasType(id, HN)){  //new selection, wrong type

                                changeCanvasCursor(arrow);

                                unselect();

                                currentselection = 0;

                                selected_node = 0; // RJL041021

                                displayMessage("Wrong type selected; try again\n");

                                selected.changeAttribState(SResize);

                                break;    // reenter SResize for BUTTON_UP action

                        }

                        else if (currentselection != selected_node) {

                                // new type HN currentselection

                                selected_node = currentselection; // save new obj*

                                HNcurr = (struct HN*)currentselection->getcurr();

                                displayMessage("New node; reselect to confirm it");

                                fprintf(stderr,

                                   "SResize_node: curr*sel* != selected_node\n");

                                //Same state; ignore BUTTON_MOVED, wait for BUTTON_UP;

                                break;

                        }

                        else { // first selection is reconfirmed

                            assert(currentselection==selected_node);

                            DP;fprintf(stderr,

                              "SResize_node:selection confirmed: id=0x%lx\n", id);

                            assert(hasType(id,HN)); // failed 9041011; OK 041013

                                dprintdd("SNode_resize: Reconfirmed: id=%lx ==? HNid=%lx\n",

                                                     id, HNcurr->HNid);

                            assert(id==HNcurr->HNid); //failed 041012:2030,2035

                            changeCanvasCursor(movehand); //during BUTTON_MOVED

                            selectedx = sx;

                            selectedy = sy;

                            displayMessage("Drag the mouse button to resize\n");

                            savedx = center_x = currentselection->getcenterx();

                            savedy = center_y = currentselection->getcentery();

                            radius = currentselection->getradius();

 

                            first_time = TRUE;  //Another Flag Var!

                            Reconfirmed = 1;    // do BUTTON_MOVED action

                            break;

                        }

                    } // end else non-null selection

                    break; // end case BUTTON_DOWN

 

               case BUTTON_MOVED_EVENT: // new or old HN selection

                    DP;dprintdd("id = %lx, HNid = %lx\n", id, HNcurr->HNid);

                    assert(hasType(id,HN)); // failed 041011,12: invalid id

                    if (Reconfirmed) {  // old HN reselected

                        assert(first_time == TRUE); //remove flag if superfluous

                        DP;doresize((int)event->x, (int)event->y, id);

                        // doresize clears first_time

                    }

                    break;  // end BUTTON_MOVED

 

               case BUTTON_UP_EVENT:

                    if (!Reconfirmed) { // same next state?

                        changeCanvasCursor(arrow);

                        // first_time == FALSE; // skip MOVED:doresize

                        break;

                    }

                    else  { // assert(Reconfirmed);cursor: movehand;finish node_resize:

                        center_x = currentselection->getcenterx();

                        center_y = currentselection->getcentery();

                        temp_x = event->x;//DC

                        temp_y = event->y;

                        diff_x = temp_x - center_x; //DC

                        diff_y = temp_y - center_y;

                        strcpy(curr_shape, currentselection->getshape());

                        if ((int)curr_shape[0] == 'C' || (int)curr_shape[0] == 'c'){

                                squares = (double)(diff_x * diff_x + diff_y * diff_y);

                                temp_radius = (float)sqrt(squares) * 2.0;

                                currentselection->setradius(temp_radius,temp_radius);

                        }else{

                                if(diff_x < 0) diff_x = -diff_x ;

                                if(diff_y < 0) diff_y = -diff_y ;

                                currentselection->setradius(diff_x*2.0, diff_y*2.0);

                        }

                        topobject->dorecalc((hcg_key)currentselection->getid());

                        position_text(); // gets its own local id via getid

                        // OK to repeat node_resize for THIS node in state SNode_resize

                        break;

                    } // end if..else

                    break;  // end case BUTTON_UP

 

                default:  /* illegal value for button_op variable  */

                        PostErrorMsg(SResize_node);

                        break;

            } // end switch(button_op)

            break;      // RJL041021

        // end case SResize_node

 

        default:

                fprintf(stderr, "Out of State in function node_resize.\n");

                fprintf(stderr, "switch arg  state=0x%x\n", state);

                fprintf(stderr, "Report this to Professor Lechner.\n");

                break;

 

    } // end switch(state)

 

}  // end node_resize()

 

/********************************************************/

/* doresize() client: node_resize: state SResize_node:  */

/* doresize is done on each BUTTON_MOVED event          */

/* Args are float event->x, event->y (= centerx,y       */

/* after first BUTTON_MOVED increment)                  */

/* TBD: switch(shape) cases should be class-specific    */

/* override methods.                                    */

/********************************************************/

void doresize(int x, int y, hcg_key id)

{

    float curr_x,curr_y,center_x,center_y;

    float temp_x,temp_y,diff_x,diff_y;

    static float last_radius,last_width,last_height;

    double squares;

    char curr_shape[20];

    extern int first_time; // in node_resize

/*  Checks No longer needed - done BEFORE BUTTON_MOVED action call RJL041011 */

    EP;assert(currentselection!=0 && id == HNcurr->HNid && \

                HNcurr==(struct HN*)currentselection->getcurr() );

    curr_x = (float)x; // new x

    curr_y = (float)y;

    temp_x = currentselection->getcenterx();// old x

    temp_y = currentselection->getcentery();

    strcpy( curr_shape, currentselection->getshape()); //invariant

    center_x = currentselection->getcenterx();

    center_y = currentselection->getcentery();

    if(curr_shape[0] == 'C' || curr_shape[0] == 'c'){

            if(first_time){

                first_time = FALSE;

                last_radius = currentselection->getradius();

                drawimage(center_x,center_y,last_radius*2.0,

                        last_radius*2.0); // erase original circle?

            }

            else { // redraw at new location and size:

                diff_x = fabs(curr_x - temp_x);

                diff_y = fabs(curr_y - temp_y);

                squares = (double)(diff_x*diff_x + diff_y*diff_y);

                last_radius = (float)sqrt(squares); // delta-center length

                drawimage(center_x,center_y,last_radius*2.0,

                        last_radius*2.0); // draw new circle?

            }

    } // end circular shape move

    else {  // shape not circular

            center_x = currentselection->getcenterx(); // old position

            center_y = currentselection->getcentery();

            if(first_time){

              first_time = FALSE;

              last_width = currentselection->getwidth(); // old dimensions

              last_height = currentselection->getheight();

              switch(curr_shape[0]){ // assert non-circular; erase old shape

                // this switch is a crutch to avoid polymorphic shape subclass:draw()

                case 'E':

                case 'e':

                   drawimage(center_x,center_y,last_width*2.0,

                                last_height*2.0);

                   break;

                case 'R':

                case 'r':

                   drawrectangular(center_x,center_y,last_width*2.0,

                                last_height*2.0);

                   break;

                case 'F':

                case 'f':

                   drawfile(center_x,center_y,last_width*2.0,

                                last_height*2.0);

                   break;

                case 'O':

                case 'o':

                   drawoutput(center_x,center_y,last_width*2.0,

                                last_height*2.0);

                   break;

                case 'I':

                case 'i':

                   drawinput(center_x,center_y,last_width*2.0,

                        last_height*2.0);

                  break;

 

                default:

                        break;

              } // end switch( shape)

            } // end if(first_time); first_time = FALSE now

            else{ // not first_time -  erase prior shape:

              switch(curr_shape[0]){

                case 'E':

                case 'e':

                   drawimage(center_x,center_y,last_width*2.0,

                                last_height*2.0);

                   break;

                case 'R':

                case 'r':

                   drawrectangular(center_x,center_y,last_width*2.0,

                                last_height*2.0);

                   break;

                case 'F':

                case 'f':

                   drawfile(center_x,center_y,last_width*2.0,

                                last_height*2.0);

                   break;

                case 'O':

                case 'o':

                   drawoutput(center_x,center_y,last_width*2.0,

                                last_height*2.0);

                   break;

                case 'I':

                case 'i':

                   drawinput(center_x,center_y,last_width*2.0,

                        last_height*2.0);

                   break;

                default:

                break;

             }

            } // end not first_time

            // now redraw same non-circular shape in new size:

            last_width = diff_x = fabs(curr_x - temp_x);

            last_height = diff_y = fabs(curr_y - temp_y);

            switch(curr_shape[0]){

              case 'E':

              case 'e':

                 drawimage(center_x,center_y,last_width*2.0,

                        last_height*2.0);

              break;

              case 'R':

              case 'r':

                 drawrectangular(center_x,center_y,last_width*2.0,

                        last_height*2.0);

              break;

              case 'F':

              case 'f':

                 drawfile(center_x,center_y,last_width*2.0,

                        last_height*2.0);

              break;

              case 'O':

              case 'o':

                   drawoutput(center_x,center_y,last_width*2.0,

                                last_height*2.0);

               break;

               case 'I':

               case 'i':

                   drawinput(center_x,center_y,last_width*2.0,

                        last_height*2.0);

               break;

               default:

                break;

            } // end  switch(shape)

   } // end non-circular shapes

} // end do_resize:480:828