예제 #1
0
파일: ttkManager.c 프로젝트: Starlink/tk
/* ++ Ttk_PlaceSlave --
 * 	Set the position and size of the specified slave window.
 *
 * NOTES:
 * 	Contrary to documentation, Tk_MaintainGeometry doesn't always
 * 	map the slave.
 */
void Ttk_PlaceSlave(
    Ttk_Manager *mgr, int slaveIndex, int x, int y, int width, int height)
{
    Ttk_Slave *slave = mgr->slaves[slaveIndex];
    Tk_MaintainGeometry(slave->slaveWindow,mgr->masterWindow,x,y,width,height);
    slave->flags |= SLAVE_MAPPED;
    if (Tk_IsMapped(mgr->masterWindow)) {
	Tk_MapWindow(slave->slaveWindow);
    }
}
예제 #2
0
static void
RecomputePlacement(
    ClientData clientData)	/* Pointer to Master record. */
{
    register Master *masterPtr = clientData;
    register Slave *slavePtr;
    int x, y, width, height, tmp;
    int masterWidth, masterHeight, masterX, masterY;
    double x1, y1, x2, y2;
    int abort;			/* May get set to non-zero to abort this
				 * placement operation. */

    masterPtr->flags &= ~PARENT_RECONFIG_PENDING;

    /*
     * Abort any nested call to RecomputePlacement for this window, since
     * we'll do everything necessary here, and set up so this call can be
     * aborted if necessary.
     */

    if (masterPtr->abortPtr != NULL) {
	*masterPtr->abortPtr = 1;
    }
    masterPtr->abortPtr = &abort;
    abort = 0;
    Tcl_Preserve(masterPtr);

    /*
     * Iterate over all the slaves for the master. Each slave's geometry can
     * be computed independently of the other slaves. Changes to the window's
     * structure could cause almost anything to happen, including deleting the
     * parent or child. If this happens, we'll be told to abort.
     */

    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort;
	    slavePtr = slavePtr->nextPtr) {
	/*
	 * Step 1: compute size and borderwidth of master, taking into account
	 * desired border mode.
	 */

	masterX = masterY = 0;
	masterWidth = Tk_Width(masterPtr->tkwin);
	masterHeight = Tk_Height(masterPtr->tkwin);
	if (slavePtr->borderMode == BM_INSIDE) {
	    masterX = Tk_InternalBorderLeft(masterPtr->tkwin);
	    masterY = Tk_InternalBorderTop(masterPtr->tkwin);
	    masterWidth -= masterX + Tk_InternalBorderRight(masterPtr->tkwin);
	    masterHeight -= masterY +
		    Tk_InternalBorderBottom(masterPtr->tkwin);
	} else if (slavePtr->borderMode == BM_OUTSIDE) {
	    masterX = masterY = -Tk_Changes(masterPtr->tkwin)->border_width;
	    masterWidth -= 2 * masterX;
	    masterHeight -= 2 * masterY;
	}

	/*
	 * Step 2: compute size of slave (outside dimensions including border)
	 * and location of anchor point within master.
	 */

	x1 = slavePtr->x + masterX + (slavePtr->relX*masterWidth);
	x = (int) (x1 + ((x1 > 0) ? 0.5 : -0.5));
	y1 = slavePtr->y + masterY + (slavePtr->relY*masterHeight);
	y = (int) (y1 + ((y1 > 0) ? 0.5 : -0.5));
	if (slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH)) {
	    width = 0;
	    if (slavePtr->flags & CHILD_WIDTH) {
		width += slavePtr->width;
	    }
	    if (slavePtr->flags & CHILD_REL_WIDTH) {
		/*
		 * The code below is a bit tricky. In order to round correctly
		 * when both relX and relWidth are specified, compute the
		 * location of the right edge and round that, then compute
		 * width. If we compute the width and round it, rounding
		 * errors in relX and relWidth accumulate.
		 */

		x2 = x1 + (slavePtr->relWidth*masterWidth);
		tmp = (int) (x2 + ((x2 > 0) ? 0.5 : -0.5));
		width += tmp - x;
	    }
	} else {
	    width = Tk_ReqWidth(slavePtr->tkwin)
		    + 2*Tk_Changes(slavePtr->tkwin)->border_width;
	}
	if (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT)) {
	    height = 0;
	    if (slavePtr->flags & CHILD_HEIGHT) {
		height += slavePtr->height;
	    }
	    if (slavePtr->flags & CHILD_REL_HEIGHT) {
		/*
		 * See note above for rounding errors in width computation.
		 */

		y2 = y1 + (slavePtr->relHeight*masterHeight);
		tmp = (int) (y2 + ((y2 > 0) ? 0.5 : -0.5));
		height += tmp - y;
	    }
	} else {
	    height = Tk_ReqHeight(slavePtr->tkwin)
		    + 2*Tk_Changes(slavePtr->tkwin)->border_width;
	}

	/*
	 * Step 3: adjust the x and y positions so that the desired anchor
	 * point on the slave appears at that position. Also adjust for the
	 * border mode and master's border.
	 */

	switch (slavePtr->anchor) {
	case TK_ANCHOR_N:
	    x -= width/2;
	    break;
	case TK_ANCHOR_NE:
	    x -= width;
	    break;
	case TK_ANCHOR_E:
	    x -= width;
	    y -= height/2;
	    break;
	case TK_ANCHOR_SE:
	    x -= width;
	    y -= height;
	    break;
	case TK_ANCHOR_S:
	    x -= width/2;
	    y -= height;
	    break;
	case TK_ANCHOR_SW:
	    y -= height;
	    break;
	case TK_ANCHOR_W:
	    y -= height/2;
	    break;
	case TK_ANCHOR_NW:
	    break;
	case TK_ANCHOR_CENTER:
	    x -= width/2;
	    y -= height/2;
	    break;
	}

	/*
	 * Step 4: adjust width and height again to reflect inside dimensions
	 * of window rather than outside. Also make sure that the width and
	 * height aren't zero.
	 */

	width -= 2*Tk_Changes(slavePtr->tkwin)->border_width;
	height -= 2*Tk_Changes(slavePtr->tkwin)->border_width;
	if (width <= 0) {
	    width = 1;
	}
	if (height <= 0) {
	    height = 1;
	}

	/*
	 * Step 5: reconfigure the window and map it if needed. If the slave
	 * is a child of the master, we do this ourselves. If the slave isn't
	 * a child of the master, let Tk_MaintainGeometry do the work (it will
	 * re-adjust things as relevant windows map, unmap, and move).
	 */

	if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) {
	    if ((x != Tk_X(slavePtr->tkwin))
		    || (y != Tk_Y(slavePtr->tkwin))
		    || (width != Tk_Width(slavePtr->tkwin))
		    || (height != Tk_Height(slavePtr->tkwin))) {
		Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height);
	    }
            if (abort) {
                break;
            }

	    /*
	     * Don't map the slave unless the master is mapped: the slave will
	     * get mapped later, when the master is mapped.
	     */

	    if (Tk_IsMapped(masterPtr->tkwin)) {
		Tk_MapWindow(slavePtr->tkwin);
	    }
	} else {
	    if ((width <= 0) || (height <= 0)) {
		Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin);
		Tk_UnmapWindow(slavePtr->tkwin);
	    } else {
		Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin,
			x, y, width, height);
	    }
	}
    }

    masterPtr->abortPtr = NULL;
    Tcl_Release(masterPtr);
}
예제 #3
0
파일: tkTextWind.c 프로젝트: das/tcltk
void
TkTextEmbWinDisplayProc(
    TkText *textPtr,		/* Information about text widget. */
    TkTextDispChunk *chunkPtr,	/* Chunk that is to be drawn. */
    int x,			/* X-position in dst at which to draw this
				 * chunk (differs from the x-position in the
				 * chunk because of scrolling). */
    int y,			/* Top of rectangular bounding box for line:
				 * tells where to draw this chunk in dst
				 * (x-position is in the chunk itself). */
    int lineHeight,		/* Total height of line. */
    int baseline,		/* Offset of baseline from y. */
    Display *display,		/* Display to use for drawing (unused).  */
    Drawable dst,		/* Pixmap or window in which to draw
				 * (unused).  */
    int screenY)		/* Y-coordinate in text window that
				 * corresponds to y. */
{
    int lineX, windowX, windowY, width, height;
    Tk_Window tkwin;
    TkTextSegment *ewPtr = chunkPtr->clientData;
    TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);

    if (client == NULL) {
	return;
    }

    tkwin = client->tkwin;
    if (tkwin == NULL) {
	return;
    }

    if ((x + chunkPtr->width) <= 0) {
	/*
	 * The window is off-screen; just unmap it.
	 */

	if (textPtr->tkwin != Tk_Parent(tkwin)) {
	    Tk_UnmaintainGeometry(tkwin, textPtr->tkwin);
	} else {
	    Tk_UnmapWindow(tkwin);
	}
	return;
    }

    /*
     * Compute the window's location and size in the text widget, taking into
     * account the align and stretch values for the window.
     */

    EmbWinBboxProc(textPtr, chunkPtr, 0, screenY, lineHeight, baseline,
	    &lineX, &windowY, &width, &height);
    windowX = lineX - chunkPtr->x + x;

    if (textPtr->tkwin == Tk_Parent(tkwin)) {
	if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin))
		|| (Tk_ReqWidth(tkwin) != Tk_Width(tkwin))
		|| (height != Tk_Height(tkwin))) {
	    Tk_MoveResizeWindow(tkwin, windowX, windowY, width, height);
	}
	Tk_MapWindow(tkwin);
    } else {
	Tk_MaintainGeometry(tkwin, textPtr->tkwin, windowX, windowY,
		width, height);
    }

    /*
     * Mark the window as displayed so that it won't get unmapped.
     */

    client->displayed = 1;
}
예제 #4
0
파일: tkCanvWind.c 프로젝트: tcltk/tk
static void
DisplayWinItem(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    Tk_Item *itemPtr,		/* Item to be displayed. */
    Display *display,		/* Display on which to draw item. */
    Drawable drawable,		/* Pixmap or window in which to draw item. */
    int regionX, int regionY, int regionWidth, int regionHeight)
				/* Describes region of canvas that must be
				 * redisplayed (not used). */
{
    WindowItem *winItemPtr = (WindowItem *) itemPtr;
    int width, height;
    short x, y;
    Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
    Tk_State state = itemPtr->state;

    if (winItemPtr->tkwin == NULL) {
	return;
    }
    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }

    /*
     * A drawable of None is used by the canvas UnmapNotify handler
     * to indicate that we should no longer display ourselves.
     */
    if (state == TK_STATE_HIDDEN || drawable == None) {
	if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
	    Tk_UnmapWindow(winItemPtr->tkwin);
	} else {
	    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
	}
	return;
    }
    Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1,
	    (double) winItemPtr->header.y1, &x, &y);
    width = winItemPtr->header.x2 - winItemPtr->header.x1;
    height = winItemPtr->header.y2 - winItemPtr->header.y1;

    /*
     * If the window is completely out of the visible area of the canvas then
     * unmap it. This code used not to be present (why unmap the window if it
     * isn't visible anyway?) but this could cause the window to suddenly
     * reappear if the canvas window got resized.
     */

    if (((x + width) <= 0) || ((y + height) <= 0)
	    || (x >= Tk_Width(canvasTkwin)) || (y >= Tk_Height(canvasTkwin))) {
	if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
	    Tk_UnmapWindow(winItemPtr->tkwin);
	} else {
	    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
	}
	return;
    }

    /*
     * Reposition and map the window (but in different ways depending on
     * whether the canvas is the window's parent).
     */

    if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
	if ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin))
		|| (width != Tk_Width(winItemPtr->tkwin))
		|| (height != Tk_Height(winItemPtr->tkwin))) {
	    Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height);
	}
	Tk_MapWindow(winItemPtr->tkwin);
    } else {
	Tk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y,
		width, height);
    }
}