// Start dragging an object BOOL backdrop_drag_object( BackdropInfo *info, BackdropObject *object) { struct Image *image; ULONG flags=0; // Is object already being dragged? if (object->drag_info) return 1; // Is there a select image? if (object->icon->do_Gadget.SelectRender && (object->icon->do_Gadget.Flags&GFLG_GADGHIMAGE)) { image=(struct Image *)object->icon->do_Gadget.SelectRender; } // No else image=(struct Image *)object->icon->do_Gadget.GadgetRender; // Get flags if (info->flags&BDIF_CUSTOM_DRAG) { // Custom drag flags=DRAGF_CUSTOM; // Opaque? if (environment->env->desktop_flags&DESKTOPF_QUICK_DRAG) flags|=DRAGF_NO_MASK; } // Get drag info if (!(object->drag_info= GetDragInfo( info->window, &GUI->drag_screen_rp, (image->Width<object->pos.Width)?object->pos.Width:image->Width, (image->Height<object->pos.Height)?object->pos.Height:image->Height, flags))) return 0; // Get image to drag backdrop_draw_object(info,object,0,&object->drag_info->drag_rp,0,0); // Get mask if (environment->env->desktop_flags&DESKTOPF_QUICK_DRAG) object->drag_info->flags|=DRAGF_OPAQUE; else if (environment->env->desktop_flags&DESKTOPF_TRANSPARENCY) object->drag_info->flags|=DRAGF_TRANSPARENT; else object->drag_info->flags|=DRAGF_TRANSPARENT|DRAGF_OPAQUE; GetDragMask(object->drag_info); return 1; }
// Draw an object void backdrop_draw_object( BackdropInfo *info, BackdropObject *object, UWORD flags, struct RastPort *rp, short left, short top) { UBYTE fpen=1,bpen=0,drawmode=JAM2,opus_drawmode=JAM2; UWORD *imagedata=0; struct Image *image=0; struct Rectangle rect; short len; BOOL comp=0,draw=1,state=0; short has_border; // No icon? if (!object->icon) return; // See if icon has no border has_border=backdrop_icon_border(object); // Not just clearing image? if (!(flags&BRENDERF_CLEAR)) { // Get image to render if ((image=(struct Image *)object->icon->do_Gadget.GadgetRender)) imagedata=image->ImageData; // Is icon selected? if (object->state) { // Is there a select image? if (object->icon->do_Gadget.SelectRender && (object->icon->do_Gadget.Flags&GFLG_GADGHIMAGE)) { if ((image=(struct Image *)object->icon->do_Gadget.SelectRender)) imagedata=image->ImageData; state=1; } else comp=1; } } #ifdef USE_DRAWICONSTATE if (GetIconRectangle( rp, object->icon, NULL, &rect, ICONDRAWA_Borderless, TRUE, TAG_DONE)) { object->pos.Width = rect.MaxX - rect.MinX + 1; object->pos.Height = rect.MaxY - rect.MinY + 1; } #elif defined(__MORPHOS__) if (ISOWN(object->icon)) { struct OwnDiskObject *o = (APTR)object->icon; object->pos.Width = o->pngimage_width; object->pos.Height = o->pngimage_height; } #endif // Get object position if (flags&BRENDERF_REAL) { short border_x=0,border_y_top=0,border_y_bottom=0; // Border? if (has_border) { // Use default border border_x=ICON_BORDER_X; border_y_top=ICON_BORDER_Y_TOP; border_y_bottom=ICON_BORDER_Y_BOTTOM; } // Calculate full size object->full_size.MinX=left-border_x; object->full_size.MinY=top-border_y_top; object->full_size.MaxX=left+object->pos.Width+border_x-1; object->full_size.MaxY=top+object->pos.Height+border_y_bottom-1; // Get image rectangle rect.MinX=object->full_size.MinX+(info->size.MinX-info->offset_x); rect.MinY=object->full_size.MinY+(info->size.MinY-info->offset_y); rect.MaxX=object->full_size.MaxX+(info->size.MinX-info->offset_x); rect.MaxY=object->full_size.MaxY+(info->size.MinY-info->offset_y); // Store position object->show_rect=rect; object->image_rect=rect; // Is object offscreen? if (rect.MaxX<info->size.MinX || rect.MaxY<info->size.MinY || rect.MinX>info->size.MaxX || rect.MinY>info->size.MaxY) draw=0; // Offset by coordinates left+=info->size.MinX-info->offset_x; top+=info->size.MinY-info->offset_y; } else { rect.MinX=left; rect.MinY=top; rect.MaxX=left+object->pos.Width-1; rect.MaxY=top+object->pos.Height-1; } // Clear area? if (flags&BRENDERF_CLEAR) { // Ok to draw? if (draw) { // Clear whole icon? if (!(flags&BRENDERF_LABEL)) { EraseRect(rp,rect.MinX,rect.MinY,rect.MaxX,rect.MaxY); } } // Can't draw else flags&=~BRENDERF_CLEAR; } // Object state changed? else if (object->flags&BDOF_STATE_CHANGE) { #ifndef USE_DRAWICONSTATE // Need to clear if transparent #if !defined(__MORPHOS__) if (!has_border) #endif EraseRect(rp,rect.MinX,rect.MinY,rect.MaxX,rect.MaxY); #endif object->flags&=~BDOF_STATE_CHANGE; } // Draw as normal if (!(flags&BRENDERF_CLEAR)) { // Not drawing if no image if (!imagedata) draw=0; // Ok to draw? if (draw) { struct BitMap bitmap; BOOL use_mask=0; // Full icon? if (flags&BRENDERF_REAL) { // Want border? if (has_border) { // Draw border around icon DrawBox(rp,&rect,GUI->draw_info,object->state); // Get background colour #ifdef USE_64BIT SetAPen( rp, (object->flags&BDOF_BACKGROUND)? object->pen: GUI->draw_info->dri_Pens[BACKGROUNDPEN]); #else SetAPen( rp, (object->flags&BDOF_BACKGROUND)? object->size: GUI->draw_info->dri_Pens[BACKGROUNDPEN]); #endif // Clear boundary around image #ifdef USE_DRAWICONSTATE RectFill(rp,rect.MinX+1,rect.MinY+1,rect.MaxX-1,rect.MaxY-1); #else RectFill(rp,rect.MinX+1,rect.MinY+1,rect.MaxX-1,rect.MinY+2); RectFill(rp,rect.MinX+1,rect.MinY+1,rect.MinX+3,rect.MaxY-1); RectFill(rp,rect.MinX+4,rect.MaxY-3,rect.MaxX-1,rect.MaxY-1); RectFill(rp,rect.MaxX-3,rect.MinY+3,rect.MaxX-1,rect.MaxY-4); #endif } #ifdef USE_DRAWICONSTATE else { EraseRect(rp,rect.MinX,rect.MinY,rect.MaxX,rect.MaxY); } #endif } #ifdef USE_DRAWICONSTATE DrawIconState( rp, object->icon, NULL, left, top, object->state ? IDS_SELECTED : IDS_NORMAL, ICONDRAWA_Frameless, TRUE, ICONDRAWA_Borderless, TRUE, ICONDRAWA_EraseBackground, FALSE, TAG_DONE); #else #if defined(__MORPHOS__) if (ISOWN(object->icon)) { IPTR tags[] = { BLTBMA_USESOURCEALPHA, TRUE, TAG_DONE }; struct OwnDiskObject *o = (APTR)object->icon; BltBitMapRastPortAlpha(o->pngimage, 0, 0, rp, left, top, o->pngimage_width, o->pngimage_height, (struct TagItem *)&tags); if (object->state) { ProcessPixelArray(rp, left, top, o->pngimage_width, o->pngimage_height, POP_TINT, 0x5082ff, NULL); } } else { #endif // Get image as a bitmap backdrop_image_bitmap(info,image,imagedata,&bitmap); // Using a mask (no border)? if (!has_border && object->image_mask[state]) { // Draw using a mask BltMaskBitMapRastPort( &bitmap,0,0, rp,left,top, image->Width,image->Height, 0xe0, (PLANEPTR)object->image_mask[state]); use_mask=1; } // Draw normally else { // Draw image BltBitMapRastPort( &bitmap,0,0, rp,left,top, image->Width,image->Height, 0xc0); } // Complement? if (comp) { DragInfo *drag_info; UBYTE mask; // Only complement to image depth mask=rp->Mask; SetWrMsk(rp,image->PlanePick); // Need backfill? if ((object->icon->do_Gadget.Flags&GFLG_GADGBACKFILL) && (drag_info=GetDragInfo(info->window,0,-object->pos.Width,-object->pos.Height,0))) { // Draw icon into drag buffer BltBitMapRastPort( &bitmap,0,0, &drag_info->drag_rp,0,0, image->Width,image->Height, 0xc0); // Build mask GetDragMask(drag_info); // Complement area with mask BltMaskBitMapRastPort( &drag_info->drag_bm, 0,0, rp, left,top, image->Width, image->Height, 0x20, (PLANEPTR)drag_info->bob.ImageShadow); // Free temporary drag info FreeDragInfo(drag_info); } // Just complement image else { ClipBlit( rp, left,top, rp, left,top, image->Width, image->Height, 0x50); } // Restore mask SetWrMsk(rp,mask); } #if defined(__MORPHOS__) } #endif #endif // Left out (on desktop), or a link? if (!(environment->env->desktop_flags&DESKTOPF_NO_ARROW) && ((object->type==BDO_LEFT_OUT && !(object->flags&BDOF_DESKTOP_FOLDER) && info->flags&BDIF_MAIN_DESKTOP) || object->flags&BDOF_LINK_ICON)) { struct Image *image; // Get correct image for this resolution image=(GUI->screen_info&SCRI_LORES)?&arrow_image[1]:&arrow_image[0]; // Is object big enough for the 'shortcut arrow'? if (object->pos.Width>(image->Width<<1) && object->pos.Height>image->Height+4) { // Draw arrow in bottom-left corner DrawImage(rp,image,rect.MinX,rect.MaxY-image->Height+1); } } // Ghosted icon? if (object->flags&BDOF_GHOSTED) { // Draw ghosting over the icon backdrop_draw_icon_ghost(rp,&rect,(use_mask)?(PLANEPTR)object->image_mask[state]:0); } } // Get pens from configuration fpen=(info->flags&BDIF_MAIN_DESKTOP)?environment->env->icon_fpen:environment->env->iconw_fpen; bpen=(info->flags&BDIF_MAIN_DESKTOP)?environment->env->icon_bpen:environment->env->iconw_bpen; drawmode=(info->flags&BDIF_MAIN_DESKTOP)?environment->env->icon_style:environment->env->iconw_style; opus_drawmode=drawmode; // Shadow/Outline? if (drawmode==MODE_SHADOW || drawmode==MODE_OUTLINE) { UBYTE temp; // Set back to JAM1 drawmode=JAM1; // Swap the pens temp=fpen; fpen=bpen; bpen=temp; } // Fix pens for user colours if (fpen>=4 && fpen<252) fpen=GUI->pens[fpen-4]; if (bpen>=4 && bpen<252) bpen=GUI->pens[bpen-4]; // Use fast call under 39 if(((struct Library *)GfxBase)->lib_Version>=39) { SetABPenDrMd(rp,fpen,bpen,drawmode); } else { SetAPen(rp,fpen); SetBPen(rp,bpen); SetDrMd(rp,drawmode); } } // Full icon? if (flags&BRENDERF_REAL && !(object->flags&BDOF_NO_LABEL)) { char *name,namebuf[40]; // Bad disk? if (object->type==BDO_BAD_DISK) { // Get bad disk name backdrop_bad_disk_name(object,namebuf); name=namebuf; } // Custom label? else if (object->flags&BDOF_CUSTOM_LABEL) name=object->device_name; // Get name pointer else name=object->name; // Get text length if ((len=strlen(name))) { struct TextExtent extent; short max_width=0,loop,textx,texty; // Splitting long labels? if (environment->env->desktop_flags&DESKTOPF_SPLIT_LABELS) { // Calculate maximum text width (minimum 6 chars) max_width=RECTWIDTH(&rect)+(RECTWIDTH(&rect)>>1); if (max_width<rp->Font->tf_XSize*6) max_width=rp->Font->tf_XSize*6; } // Position for text textx=rect.MinX+(RECTWIDTH(&rect)>>1); texty=rect.MaxY+ICON_LABEL_SPACE+rp->TxBaseline+((opus_drawmode==MODE_OUTLINE)?1:0); Move(rp,textx,texty); // Get text pixel size TextMultiLine(rp,name,len,max_width,TMLF_CENTER|TMLF_EXTENT,&extent); // Fix extent for shadow/outline if (opus_drawmode==MODE_SHADOW) { extent.te_Extent.MaxX++; extent.te_Width++; extent.te_Height++; } else if (opus_drawmode==MODE_OUTLINE) { extent.te_Extent.MinX--; extent.te_Extent.MaxX++; extent.te_Width+=2; extent.te_Height+=2; } // Stretch out rectangle sides if necessary if (extent.te_Extent.MinX<rect.MinX) object->full_size.MinX-=rect.MinX-extent.te_Extent.MinX; if (extent.te_Extent.MaxX>rect.MaxX) object->full_size.MaxX+=extent.te_Extent.MaxX-rect.MaxX; if (object->show_rect.MinX>extent.te_Extent.MinX) object->show_rect.MinX=extent.te_Extent.MinX; if (object->show_rect.MaxX<extent.te_Extent.MinX+extent.te_Width-1) object->show_rect.MaxX=extent.te_Extent.MinX+extent.te_Width-1; // Save bottom of text object->show_rect.MaxY+=ICON_LABEL_SPACE+extent.te_Height; // +((opus_drawmode==MODE_OUTLINE)?1:0); object->full_size.MaxY+=ICON_LABEL_SPACE+extent.te_Height; // +((opus_drawmode==MODE_OUTLINE)?1:0); // Clear? if (flags&BRENDERF_CLEAR) { EraseRect(rp, extent.te_Extent.MinX,rect.MaxY+ICON_LABEL_SPACE+((opus_drawmode==MODE_OUTLINE)?1:0), extent.te_Extent.MinX+extent.te_Width-1,rect.MaxY+ICON_LABEL_SPACE+extent.te_Height-1); } // Draw text else { // Is object selected? if (object->flags&BDOF_SELECTED) { if (drawmode==JAM2) SetDrMd(rp,INVERSVID|JAM2); else if (fpen!=GUI->draw_info->dri_Pens[HIGHLIGHTTEXTPEN]) SetAPen(rp,GUI->draw_info->dri_Pens[HIGHLIGHTTEXTPEN]); else SetAPen(rp,GUI->draw_info->dri_Pens[BACKGROUNDPEN]); } // Shadow if (opus_drawmode==MODE_SHADOW) { // Draw shadow text first Move(rp,textx+1,texty+1); TextMultiLine(rp,name,len,max_width,TMLF_CENTER,0); // Draw text SetAPen(rp,bpen); Move(rp,textx,texty); TextMultiLine(rp,name,len,max_width,TMLF_CENTER,0); } // Normal text else if (opus_drawmode!=MODE_OUTLINE) { // Render text TextMultiLine(rp,name,len,max_width,TMLF_CENTER,0); } // Outline else { Move(rp,textx+1,texty+1); for (loop=0;loop<5;loop++) { // Render text TextMultiLine(rp,name,len,max_width,TMLF_CENTER,0); // Doing shadow? if (loop<4) { short s_x=0,s_y=0; // Switch to other pen? if (loop==3) SetAPen(rp,bpen); // Get the new offsets else if (loop==0) { s_x=-1; s_y=1; } else if (loop==1) { s_x=-1; s_y=-1; } else if (loop==2) { s_x=1; s_y=-1; } // Position for text Move(rp,textx+s_x,texty+s_y); } } } // Reset draw mode if necessary if (object->flags&BDOF_SELECTED) SetDrMd(rp,drawmode); } }
// Start dragging a button void buttons_start_drag( Buttons *buttons, short x, short y, short col, short row) { struct Rectangle rect; // Store column and row buttons->drag_col=buttons->button_sel_col; buttons->drag_row=buttons->button_sel_row; // Save button pointer buttons->button_drag_button=buttons->button_sel_button; // Get draginfo if (!(buttons->drag_info= GetDragInfo( buttons->window, 0, buttons->button_width, buttons->button_height, DRAGF_NEED_GELS|DRAGF_CUSTOM))) return; // Get button coordinates buttons_get_rect(buttons,col,row,&rect); // Set opaque flag buttons->drag_info->flags|=DRAGF_OPAQUE; // Redraw button buttons_show_button( buttons, buttons->button_drag_button, buttons->drag_col, buttons->drag_row, buttons->button_drag_button->current, 0); // Draw button image for drag SetDrMd(&buttons->drag_info->drag_rp,JAM1); SetFont(&buttons->drag_info->drag_rp,buttons->window->RPort->Font); buttons_show_button( buttons, buttons->button_drag_button, 0,0, FTYPE_LEFT_BUTTON, &buttons->drag_info->drag_rp); // Calculate mask GetDragMask(buttons->drag_info); // Calculate offset buttons->drag_x_offset-=rect.MinX; buttons->drag_y_offset-=rect.MinY; // Initialise tick count buttons->tick_count=1; buttons->last_tick=0; // Show drag image buttons_show_drag(buttons,x,y); }