void buttons_context_draw(const bContext *C, uiLayout *layout)
{
	SpaceButs *sbuts = CTX_wm_space_buts(C);
	ButsContextPath *path = sbuts->path;
	uiLayout *row;
	uiBlock *block;
	uiBut *but;
	PointerRNA *ptr;
	char namebuf[128], *name;
	int a, icon;

	if (!path)
		return;

	row = uiLayoutRow(layout, true);
	uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);

	block = uiLayoutGetBlock(row);
	UI_block_emboss_set(block, UI_EMBOSS_NONE);
	but = uiDefIconButBitC(block, UI_BTYPE_ICON_TOGGLE, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag,
	                       0, 0, 0, 0, TIP_("Follow context or keep fixed datablock displayed"));
	UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
	UI_but_func_set(but, pin_cb, NULL, NULL);

	for (a = 0; a < path->len; a++) {
		ptr = &path->ptr[a];

		if (a != 0)
			uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC);

		if (ptr->data) {
			icon = RNA_struct_ui_icon(ptr->type);
			name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);

			if (name) {
				if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene)
					uiItemLDrag(row, ptr, "", icon);  /* save some space */
				else
					uiItemLDrag(row, ptr, name, icon);

				if (name != namebuf)
					MEM_freeN(name);
			}
			else
				uiItemL(row, "", icon);
		}
	}
}
Example #2
0
void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
{
  ScrArea *sa = CTX_wm_area(C);
  SpaceClip *sc = CTX_wm_space_clip(C);
  View2D *v2d = &ar->v2d;
  MovieClip *clip = ED_space_clip_get_clip(sc);
  uiStyle *style = UI_style_get();
  int fontid = style->widget.uifont_id;

  if (!clip) {
    return;
  }

  MovieTracking *tracking = &clip->tracking;
  MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
  int height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);

  if (height > BLI_rcti_size_y(&v2d->mask)) {
    /* don't use totrect set, as the width stays the same
     * (NOTE: this is ok here, the configuration is pretty straightforward)
     */
    v2d->tot.ymin = (float)(-height);
  }

  /* need to do a view-sync here, so that the keys area doesn't jump around
   * (it must copy this) */
  UI_view2d_sync(NULL, sa, v2d, V2D_LOCK_COPY);

  /* loop through channels, and set up drawing depending on their type
   * first pass: just the standard GL-drawing for backdrop + text
   */
  float y = (float)CHANNEL_FIRST;

  GPUVertFormat *format = immVertexFormat();
  uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);

  immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);

  MovieTrackingDopesheetChannel *channel;
  for (channel = dopesheet->channels.first; channel; channel = channel->next) {
    float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
    float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);

    /* check if visible */
    if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
        IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
      MovieTrackingTrack *track = channel->track;
      float color[3];
      track_channel_color(track, NULL, color);
      immUniformColor3fv(color);

      immRectf(pos,
               v2d->cur.xmin,
               (float)y - CHANNEL_HEIGHT_HALF,
               v2d->cur.xmax + EXTRA_SCROLL_PAD,
               (float)y + CHANNEL_HEIGHT_HALF);
    }

    /* adjust y-position for next one */
    y -= CHANNEL_STEP;
  }
  immUnbindProgram();

  /* second pass: text */
  y = (float)CHANNEL_FIRST;

  BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);

  for (channel = dopesheet->channels.first; channel; channel = channel->next) {
    float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
    float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);

    /* check if visible */
    if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
        IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
      MovieTrackingTrack *track = channel->track;
      bool sel = (track->flag & TRACK_DOPE_SEL) != 0;

      UI_FontThemeColor(fontid, sel ? TH_TEXT_HI : TH_TEXT);

      float font_height = BLF_height(fontid, channel->name, sizeof(channel->name));
      BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD, y - font_height / 2.0f, 0.0f);
      BLF_draw(fontid, channel->name, strlen(channel->name));
    }

    /* adjust y-position for next one */
    y -= CHANNEL_STEP;
  }

  /* third pass: widgets */
  uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
  y = (float)CHANNEL_FIRST;

  /* get RNA properties (once) */
  PropertyRNA *chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock");
  BLI_assert(chan_prop_lock);

  GPU_blend(true);
  for (channel = dopesheet->channels.first; channel; channel = channel->next) {
    float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
    float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);

    /* check if visible */
    if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
        IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
      MovieTrackingTrack *track = channel->track;
      const int icon = (track->flag & TRACK_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED;
      PointerRNA ptr;

      RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, &ptr);

      UI_block_emboss_set(block, UI_EMBOSS_NONE);
      uiDefIconButR_prop(block,
                         UI_BTYPE_ICON_TOGGLE,
                         1,
                         icon,
                         v2d->cur.xmax - UI_UNIT_X - CHANNEL_PAD,
                         y - UI_UNIT_Y / 2.0f,
                         UI_UNIT_X,
                         UI_UNIT_Y,
                         &ptr,
                         chan_prop_lock,
                         0,
                         0,
                         0,
                         0,
                         0,
                         NULL);
      UI_block_emboss_set(block, UI_EMBOSS);
    }

    /* adjust y-position for next one */
    y -= CHANNEL_STEP;
  }
  GPU_blend(false);

  UI_block_end(C, block);
  UI_block_draw(C, block);
}
Example #3
0
void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
{
	bScreen *screen = CTX_wm_screen(C);
	ScrArea *sa = CTX_wm_area(C);
	View3D *v3d = sa->spacedata.first;
	Scene *scene = CTX_data_scene(C);
	ToolSettings *ts = CTX_data_tool_settings(C);
	PointerRNA v3dptr, toolsptr, sceneptr;
	Object *ob = OBACT;
	Object *obedit = CTX_data_edit_object(C);
	uiBlock *block;
	uiLayout *row;
	bool is_paint = false;
	int modeselect;
	
	RNA_pointer_create(&screen->id, &RNA_SpaceView3D, v3d, &v3dptr);
	RNA_pointer_create(&scene->id, &RNA_ToolSettings, ts, &toolsptr);
	RNA_pointer_create(&scene->id, &RNA_Scene, scene, &sceneptr);

	block = uiLayoutGetBlock(layout);
	UI_block_func_handle_set(block, do_view3d_header_buttons, NULL);

	/* other buttons: */
	UI_block_emboss_set(block, UI_EMBOSS);
	
	/* mode */
	if (ob) {
		modeselect = ob->mode;
		is_paint = ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
	}
	else {
		modeselect = OB_MODE_OBJECT;
	}

	row = uiLayoutRow(layout, false);
	{
		EnumPropertyItem *item = object_mode_items;
		const char *name = "";
		int icon = ICON_OBJECT_DATAMODE;

		while (item->identifier) {
			if (item->value == modeselect && item->identifier[0]) {
				name = IFACE_(item->name);
				icon = item->icon;
				break;
			}
			item++;
		}

		uiItemMenuEnumO(row, C, "OBJECT_OT_mode_set", "mode", name, icon);
	}

	/* Draw type */
	uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);

	if (obedit == NULL && is_paint) {
		if (ob->mode & OB_MODE_ALL_PAINT) {
			/* Only for Weight Paint. makes no sense in other paint modes. */
			row = uiLayoutRow(layout, true);
			uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		}

		/* Manipulators aren't used in paint modes */
		if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) {
			/* masks aren't used for sculpt and particle painting */
			PointerRNA meshptr;

			RNA_pointer_create(ob->data, &RNA_Mesh, ob->data, &meshptr);
			if (ob->mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT)) {
				uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
			}
			else {
				row = uiLayoutRow(layout, true);
				uiItemR(row, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
				uiItemR(row, &meshptr, "use_paint_mask_vertex", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
			}
		}
	}
	else {
		row = uiLayoutRow(layout, true);
		uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);

		/* pose/object only however we want to allow in weight paint mode too
		 * so don't be totally strict and just check not-editmode for now 
		 * XXX We never get here when we are in Weight Paint mode
		 */
		if (obedit == NULL) {
			uiItemR(row, &v3dptr, "use_pivot_point_align", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		}

		/* Transform widget / manipulators */
		row = uiLayoutRow(layout, true);
		uiItemR(row, &v3dptr, "show_manipulator", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		if (v3d->twflag & V3D_USE_MANIPULATOR) {
			uiItemR(row, &v3dptr, "transform_manipulators", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		}
		uiItemR(row, &v3dptr, "transform_orientation", 0, "", ICON_NONE);
	}

	if (obedit == NULL && v3d->localvd == NULL) {
		unsigned int ob_lay = ob ? ob->lay : 0;

		/* Layers */
		uiTemplateLayers(layout, v3d->scenelock ? &sceneptr : &v3dptr, "layers", &v3dptr, "layers_used", ob_lay);

		/* Scene lock */
		uiItemR(layout, &v3dptr, "lock_camera_and_layers", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
	}
	
	uiTemplateEditModeSelection(layout, C);
}
static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth)
{
	PointerRNA inputptr, nodeptr;
	uiBlock *block = uiLayoutGetBlock(layout);
	uiBut *bt;
	uiLayout *split, *row, *col;
	bNode *lnode;
	char label[UI_MAX_NAME_STR];
	int indent = (depth > 1) ? 2 * (depth - 1) : 0;
	int dependency_loop;

	if (input->flag & SOCK_UNAVAIL)
		return;

	/* to avoid eternal loops on cyclic dependencies */
	node->flag |= NODE_TEST;
	lnode = (input->link) ? input->link->fromnode : NULL;

	dependency_loop = (lnode && (lnode->flag & NODE_TEST));
	if (dependency_loop)
		lnode = NULL;

	/* socket RNA pointer */
	RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr);
	RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);

	/* indented label */
	memset(label, ' ', indent);
	label[indent] = '\0';
	BLI_snprintf(label, UI_MAX_NAME_STR, "%s%s:", label, IFACE_(input->name));

	/* split in label and value */
	split = uiLayoutSplit(layout, 0.35f, false);

	row = uiLayoutRow(split, true);

	if (depth > 0) {
		UI_block_emboss_set(block, UI_EMBOSS_NONE);

		if (lnode && (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) {
			int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : ICON_DISCLOSURE_TRI_DOWN;
			uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon);
		}
		else
			uiItemL(row, "", ICON_BLANK1);

		bt = block->buttons.last;
		bt->rect.xmax = UI_UNIT_X / 2;

		UI_block_emboss_set(block, UI_EMBOSS);
	}

	uiItemL(row, label, ICON_NONE);
	bt = block->buttons.last;
	bt->drawflag = UI_BUT_TEXT_LEFT;

	if (dependency_loop) {
		row = uiLayoutRow(split, false);
		uiItemL(row, IFACE_("Dependency Loop"), ICON_ERROR);
	}
	else if (lnode) {
		/* input linked to a node */
		uiTemplateNodeLink(split, ntree, node, input);

		if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) {
			if (depth == 0)
				uiItemS(layout);

			ui_node_draw_node(layout, C, ntree, lnode, depth);
		}
	}
	else {
		/* input not linked, show value */
		if (!(input->flag & SOCK_HIDE_VALUE)) {
			switch (input->type) {
				case SOCK_FLOAT:
				case SOCK_INT:
				case SOCK_BOOLEAN:
				case SOCK_RGBA:
				case SOCK_STRING:
					row = uiLayoutRow(split, true);
					uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
					break;
				case SOCK_VECTOR:
					row = uiLayoutRow(split, false);
					col = uiLayoutColumn(row, false);
					uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
					break;
					
				default:
					row = uiLayoutRow(split, false);
					break;
			}
		}
		else
			row = uiLayoutRow(split, false);

		uiTemplateNodeLink(row, ntree, node, input);
	}

	/* clear */
	node->flag &= ~NODE_TEST;
}
Example #5
0
/* driver settings for active F-Curve (only for 'Drivers' mode) */
static void graph_panel_drivers(const bContext *C, Panel *pa)
{
	bAnimListElem *ale;
	FCurve *fcu;
	ChannelDriver *driver;
	DriverVar *dvar;
	
	PointerRNA driver_ptr;
	uiLayout *col;
	uiBlock *block;
	uiBut *but;
	
	/* Get settings from context */
	if (!graph_panel_context(C, &ale, &fcu))
		return;
	driver = fcu->driver;
	
	/* set event handler for panel */
	block = uiLayoutGetBlock(pa->layout); // xxx?
	UI_block_func_handle_set(block, do_graph_region_driver_buttons, NULL);
	
	/* general actions - management */
	col = uiLayoutColumn(pa->layout, false);
	block = uiLayoutGetBlock(col);
	but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_FILE_REFRESH, IFACE_("Update Dependencies"),
	               0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
	               NULL, 0.0, 0.0, 0, 0,
	               TIP_("Force updates of dependencies"));
	UI_but_func_set(but, driver_update_flags_cb, fcu, NULL);

	but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMOUT, IFACE_("Remove Driver"),
	               0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
	               NULL, 0.0, 0.0, 0, 0,
	               TIP_("Remove this driver"));
	UI_but_funcN_set(but, driver_remove_cb, MEM_dupallocN(ale), NULL);
		
	/* driver-level settings - type, expressions, and errors */
	RNA_pointer_create(ale->id, &RNA_Driver, driver, &driver_ptr);
	
	col = uiLayoutColumn(pa->layout, true);
	block = uiLayoutGetBlock(col);
	uiItemR(col, &driver_ptr, "type", 0, NULL, ICON_NONE);

	/* show expression box if doing scripted drivers, and/or error messages when invalid drivers exist */
	if (driver->type == DRIVER_TYPE_PYTHON) {
		bool bpy_data_expr_error = (strstr(driver->expression, "bpy.data.") != NULL);
		bool bpy_ctx_expr_error  = (strstr(driver->expression, "bpy.context.") != NULL);
		
		/* expression */
		uiItemR(col, &driver_ptr, "expression", 0, IFACE_("Expr"), ICON_NONE);
		
		/* errors? */
		if ((G.f & G_SCRIPT_AUTOEXEC) == 0) {
			uiItemL(col, IFACE_("ERROR: Python auto-execution disabled"), ICON_CANCEL);
		}
		else if (driver->flag & DRIVER_FLAG_INVALID) {
			uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL);
		}
		
		/* Explicit bpy-references are evil. Warn about these to prevent errors */
		/* TODO: put these in a box? */
		if (bpy_data_expr_error || bpy_ctx_expr_error) {
			uiItemL(col, IFACE_("WARNING: Driver expression may not work correctly"), ICON_HELP);
			
			if (bpy_data_expr_error) {
				uiItemL(col, IFACE_("TIP: Use variables instead of bpy.data paths (see below)"), ICON_ERROR);
			}
			if (bpy_ctx_expr_error) {
				uiItemL(col, IFACE_("TIP: bpy.context is not safe for renderfarm usage"), ICON_ERROR);
			}
		}
	}
	else {
		/* errors? */
		if (driver->flag & DRIVER_FLAG_INVALID)
			uiItemL(col, IFACE_("ERROR: Invalid target channel(s)"), ICON_ERROR);
			
		/* Warnings about a lack of variables
		 * NOTE: The lack of variables is generally a bad thing, since it indicates
		 *       that the driver doesn't work at all. This particular scenario arises
		 *       primarily when users mistakenly try to use drivers for procedural
		 *       property animation
		 */
		if (BLI_listbase_is_empty(&driver->variables)) {
			uiItemL(col, IFACE_("ERROR: Driver is useless without any inputs"), ICON_ERROR);
			
			if (!BLI_listbase_is_empty(&fcu->modifiers)) {
				uiItemL(col, IFACE_("TIP: Use F-Curves for procedural animation instead"), ICON_INFO);
				uiItemL(col, IFACE_("F-Modifiers can generate curves for those too"), ICON_INFO);
			}
		}
	}
		
	col = uiLayoutColumn(pa->layout, true);

	if (driver->type == DRIVER_TYPE_PYTHON) {
		uiItemR(col, &driver_ptr, "use_self", 0, NULL, ICON_NONE);
	}

	/* debug setting */
	uiItemR(col, &driver_ptr, "show_debug_info", 0, NULL, ICON_NONE);
		
	/* value of driver */
	if (driver->flag & DRIVER_FLAG_SHOWDEBUG) {
		uiLayout *row = uiLayoutRow(col, true);
		char valBuf[32];
			
		uiItemL(row, IFACE_("Driver Value:"), ICON_NONE);
			
		BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval);
		uiItemL(row, valBuf, ICON_NONE);
	}
	
	/* add/copy/paste driver variables */
	{
		uiLayout *row;
		
		/* add driver variable */
		row = uiLayoutRow(pa->layout, false);
		block = uiLayoutGetBlock(row);
		but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Variable"),
	                           0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
	                           NULL, 0.0, 0.0, 0, 0,
	                           TIP_("Driver variables ensure that all dependencies will be accounted for and that drivers will update correctly"));
		UI_but_func_set(but, driver_add_var_cb, driver, NULL);
		
		/* copy/paste (as sub-row) */
		row = uiLayoutRow(row, true);
		block = uiLayoutGetBlock(row);
		
		uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_driver_variables_copy");
		uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_driver_variables_paste");
	}
	
	/* loop over targets, drawing them */
	for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
		PointerRNA dvar_ptr;
		uiLayout *box, *row;
		uiLayout *subrow, *sub;
		
		/* sub-layout column for this variable's settings */
		col = uiLayoutColumn(pa->layout, true);
		
		/* 1) header panel */
		box = uiLayoutBox(col);
		RNA_pointer_create(ale->id, &RNA_DriverVariable, dvar, &dvar_ptr);
		
		row = uiLayoutRow(box, false);
		block = uiLayoutGetBlock(row);
		
		/* 1.1) variable type and name */
		subrow = uiLayoutRow(row, true);
		
		/* 1.1.1) variable type */
		sub = uiLayoutRow(subrow, true);                     /* HACK: special group just for the enum, otherwise we */
		uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);  /*       we get ugly layout with text included too...  */
		
		uiItemR(sub, &dvar_ptr, "type", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
		
		/* 1.1.2) variable name */
		sub = uiLayoutRow(subrow, true);                       /* HACK: special group to counteract the effects of the previous */
		uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND);  /*       enum, which now pushes everything too far right         */
		
		uiItemR(sub, &dvar_ptr, "name", 0, "", ICON_NONE);
		
		/* 1.2) invalid name? */
		UI_block_emboss_set(block, UI_EMBOSS_NONE);
		
		if (dvar->flag & DVAR_FLAG_INVALID_NAME) {
			but = uiDefIconBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ERROR, 290, 0, UI_UNIT_X, UI_UNIT_Y,
			                   NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Invalid variable name, click here for details"));
			UI_but_func_set(but, driver_dvar_invalid_name_query_cb, dvar, NULL); // XXX: reports?
		}
		
		/* 1.3) remove button */
		but = uiDefIconBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y,
		                   NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Delete target variable"));
		UI_but_func_set(but, driver_delete_var_cb, driver, dvar);
		UI_block_emboss_set(block, UI_EMBOSS);
		
		
		/* 2) variable type settings */
		box = uiLayoutBox(col);
		/* controls to draw depends on the type of variable */
		switch (dvar->type) {
			case DVAR_TYPE_SINGLE_PROP:     /* single property */
				graph_panel_driverVar__singleProp(box, ale->id, dvar);
				break;
			case DVAR_TYPE_ROT_DIFF:     /* rotational difference */
				graph_panel_driverVar__rotDiff(box, ale->id, dvar);
				break;
			case DVAR_TYPE_LOC_DIFF:     /* location difference */
				graph_panel_driverVar__locDiff(box, ale->id, dvar);
				break;
			case DVAR_TYPE_TRANSFORM_CHAN:     /* transform channel */
				graph_panel_driverVar__transChan(box, ale->id, dvar);
				break;
		}
		
		/* 3) value of variable */
		if (driver->flag & DRIVER_FLAG_SHOWDEBUG) {
			char valBuf[32];
			
			box = uiLayoutBox(col);
			row = uiLayoutRow(box, true);
			uiItemL(row, IFACE_("Value:"), ICON_NONE);
			
			if ((dvar->type == DVAR_TYPE_ROT_DIFF) ||
			    (dvar->type == DVAR_TYPE_TRANSFORM_CHAN &&
			     dvar->targets[0].transChan >= DTAR_TRANSCHAN_ROTX &&
			     dvar->targets[0].transChan < DTAR_TRANSCHAN_SCALEX))
			{
				BLI_snprintf(valBuf, sizeof(valBuf), "%.3f (%4.1f°)", dvar->curval, RAD2DEGF(dvar->curval));
			}
			else {
				BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval);
			}
			
			uiItemL(row, valBuf, ICON_NONE);
		}
	}
	
	/* cleanup */
	MEM_freeN(ale);
}