예제 #1
0
        public override void ComposeElements(Context ctxStatic, ImageSurface surfaceStatic)
        {
            handleWidth     = scaled(unscaledHandleWidth) * Scale;
            handleHeight    = scaled(unscaledHandleHeight) * Scale;
            hoverTextWidth  = scaled(unscaledHoverTextHeight);
            hoverTextHeight = scaled(unscaledHoverTextHeight);
            padding         = scaled(unscaledPadding) * Scale;

            Bounds.CalcWorldBounds();

            ctxStatic.SetSourceRGBA(0, 0, 0, 0.2);
            RoundRectangle(ctxStatic, Bounds.drawX, Bounds.drawY, Bounds.InnerWidth, Bounds.InnerHeight, 1);
            ctxStatic.Fill();
            EmbossRoundRectangleElement(ctxStatic, Bounds, true, 1, 1);


            double insetWidth  = Bounds.InnerWidth - 2 * padding;
            double insetHeight = Bounds.InnerHeight - 2 * padding;


            if (alarmValue > 0 && alarmValue < maxValue)
            {
                float alarmValueRel = (float)alarmValue / maxValue;

                alarmTextureRect = new Rectangled()
                {
                    X = padding + (Bounds.InnerWidth - 2 * padding) * alarmValueRel, Y = padding, Width = (Bounds.InnerWidth - 2 * padding) * (1 - alarmValueRel), Height = Bounds.InnerHeight - 2 * padding
                };

                ctxStatic.SetSourceRGBA(0.62, 0, 0, 0.4);

                RoundRectangle(ctxStatic, Bounds.drawX + padding + insetWidth * alarmValueRel, Bounds.drawY + padding, insetWidth * (1 - alarmValueRel), insetHeight, 1);
                ctxStatic.Fill();
            }


            /*** 2. Handle ***/
            ImageSurface surface = new ImageSurface(Format.Argb32, (int)handleWidth + 4, (int)handleHeight + 4);
            Context      ctx     = genContext(surface);

            ctx.SetSourceRGBA(1, 1, 1, 0);
            ctx.Paint();

            RoundRectangle(ctx, 2, 2, handleWidth, handleHeight, 1);
            fillWithPattern(api, ctx, woodTextureName, false, true);

            ctx.SetSourceRGB(43 / 255.0, 33 / 255.0, 24 / 255.0);
            ctx.LineWidth = 2;
            ctx.Stroke();

            generateTexture(surface, ref handleTexture);
            ctx.Dispose();
            surface.Dispose();

            ComposeWaterTexture();
            ComposeHoverTextElement();
        }
예제 #2
0
        void MakeAlarmValueTexture()
        {
            float alarmValueRel = (float)(alarmValue - minValue) / (maxValue - minValue);

            alarmTextureRect = new Rectangled()
            {
                X = padding + (Bounds.InnerWidth - 2 * padding) * alarmValueRel, Y = padding, Width = (Bounds.InnerWidth - 2 * padding) * (1 - alarmValueRel), Height = Bounds.InnerHeight - 2 * padding
            };


            ImageSurface surface = new ImageSurface(Format.Argb32, (int)alarmTextureRect.Width, (int)alarmTextureRect.Height);
            Context      ctx     = genContext(surface);

            ctx.SetSourceRGBA(1, 0, 1, 0.4);

            RoundRectangle(ctx, 0, 0, alarmTextureRect.Width, alarmTextureRect.Height, GuiStyle.ElementBGRadius);
            ctx.Fill();

            generateTexture(surface, ref alarmValueTexture.TextureId);
            ctx.Dispose();
            surface.Dispose();
        }
예제 #3
0
        public override void ComposeTextElements(Context ctx, ImageSurface surface)
        {
            if (!didInit)
            {
                SetUpMovableState(null);
                didInit = true;
            }

            RoundRectangle(ctx, Bounds.bgDrawX, Bounds.bgDrawY, Bounds.OuterWidth, Bounds.OuterHeight, GuiStyle.DialogBGRadius);
            //ctx.SetSourceRGBA(GuiStyle.DialogDefaultBgColor[0], GuiStyle.DialogDefaultBgColor[1], GuiStyle.DialogDefaultBgColor[2], 1);
            //ctx.FillPreserve();

            LinearGradient gradient = new LinearGradient(0, 0, Bounds.InnerWidth, 0);

            gradient.AddColorStop(0, new Color(GuiStyle.DialogDefaultBgColor[0] * 1.4, GuiStyle.DialogDefaultBgColor[1] * 1.4, GuiStyle.DialogDefaultBgColor[2] * 1.4, 1));
            gradient.AddColorStop(0.5, new Color(GuiStyle.DialogDefaultBgColor[0] * 1.1, GuiStyle.DialogDefaultBgColor[1] * 1.1, GuiStyle.DialogDefaultBgColor[2] * 1.1, 1));
            gradient.AddColorStop(1, new Color(GuiStyle.DialogDefaultBgColor[0] * 1.4, GuiStyle.DialogDefaultBgColor[1] * 1.4, GuiStyle.DialogDefaultBgColor[2] * 1.4, 1));
            ctx.SetSource(gradient);
            ctx.FillPreserve();
            gradient.Dispose();


            Bounds.CalcWorldBounds();

            double radius = GuiStyle.DialogBGRadius;

            ctx.NewPath();
            ctx.MoveTo(Bounds.drawX, Bounds.drawY + Bounds.InnerHeight);
            ctx.LineTo(Bounds.drawX, Bounds.drawY + radius);
            ctx.Arc(Bounds.drawX + radius, Bounds.drawY + radius, radius, 180 * GameMath.DEG2RAD, 270 * GameMath.DEG2RAD);
            ctx.Arc(Bounds.drawX + Bounds.OuterWidth - radius, Bounds.drawY + radius, radius, -90 * GameMath.DEG2RAD, 0 * GameMath.DEG2RAD);
            ctx.LineTo(Bounds.drawX + Bounds.OuterWidth, Bounds.drawY + Bounds.InnerHeight);

            ctx.SetSourceRGBA(GuiStyle.TitleBarColor);
            ctx.FillPreserve();

            ctx.SetSourceRGBA(new double[] { 45 / 255.0, 35 / 255.0, 33 / 255.0, 1 });
            ctx.LineWidth = 6;
            ctx.Stroke();



            Font.SetupContext(ctx);
            DrawTextLineAt(ctx, text, scaled(GuiStyle.ElementToDialogPadding), (Bounds.InnerHeight - Font.GetFontExtents().Height) / 2 + scaled(2));

            double crossSize  = scaled(unscaledCloseIconSize);
            double menuSize   = scaled(unscaledCloseIconSize + 2);
            double crossX     = Bounds.drawX + Bounds.OuterWidth - crossSize - scaled(12);
            double iconY      = Bounds.drawY + scaled(7);
            double crossWidth = scaled(2);

            double menuX = Bounds.drawX + Bounds.OuterWidth - crossSize - menuSize - scaled(20);

            menuIconRect  = new Rectangled(Bounds.OuterWidth - crossSize - menuSize - scaled(20), scaled(6), crossSize, crossSize);
            closeIconRect = new Rectangled(Bounds.OuterWidth - crossSize - scaled(12), scaled(5), menuSize, menuSize);

            ctx.Operator = Operator.Over;
            ctx.SetSourceRGBA(0, 0, 0, 0.3);
            api.Gui.Icons.DrawCross(ctx, crossX + 2, iconY + 2, crossWidth, crossSize);
            ctx.Operator = Operator.Source;
            ctx.SetSourceRGBA(GuiStyle.DialogDefaultTextColor);
            api.Gui.Icons.DrawCross(ctx, crossX, iconY, crossWidth, crossSize);

            ctx.Operator = Operator.Over;
            api.Gui.Icons.Drawmenuicon_svg(ctx, (int)menuX + 2, (int)iconY + 2, (int)menuSize, (int)menuSize, new double[] { 0, 0, 0, 0.3 });
            ctx.Operator = Operator.Source;
            api.Gui.Icons.Drawmenuicon_svg(ctx, (int)menuX, (int)iconY + 1, (int)menuSize, (int)menuSize, GuiStyle.DialogDefaultTextColor);

            ctx.Operator = Operator.Over;

            ComposeHoverIcons();


            listMenu.Bounds.fixedX = (Bounds.absX + menuIconRect.X - Bounds.absX) / RuntimeEnv.GUIScale;

            listMenu.ComposeDynamicElements();
        }
예제 #4
0
        public override void ComposeElements(Context ctxStatic, ImageSurface surfaceStatic)
        {
            handleWidth     = scaled(unscaledHandleWidth);
            handleHeight    = scaled(unscaledHandleHeight);
            hoverTextWidth  = scaled(unscaledHoverTextHeight);
            hoverTextHeight = scaled(unscaledHoverTextHeight);
            padding         = scaled(unscaledPadding);

            Bounds.CalcWorldBounds();


            // Wood bg
            RoundRectangle(ctxStatic, Bounds.drawX, Bounds.drawY, Bounds.InnerWidth, Bounds.InnerHeight, GuiStyle.ElementBGRadius);
            fillWithPattern(api, ctxStatic, woodTextureName);

            EmbossRoundRectangleElement(ctxStatic, Bounds.drawX, Bounds.drawY, Bounds.InnerWidth, Bounds.InnerHeight);


            double insetWidth  = Bounds.InnerWidth - 2 * padding;
            double insetHeight = Bounds.InnerHeight - 2 * padding;

            // Wood Inset
            ctxStatic.SetSourceRGBA(0, 0, 0, 0.6);
            RoundRectangle(ctxStatic, Bounds.drawX + padding, Bounds.drawY + padding, insetWidth, insetHeight, GuiStyle.ElementBGRadius);
            ctxStatic.Fill();

            EmbossRoundRectangleElement(ctxStatic, Bounds.drawX + padding, Bounds.drawY + padding, insetWidth, insetHeight, true);


            if (alarmValue > 0 && alarmValue < maxValue)
            {
                float alarmValueRel = (float)alarmValue / maxValue;

                alarmTextureRect = new Rectangled()
                {
                    X = padding + (Bounds.InnerWidth - 2 * padding) * alarmValueRel, Y = padding, Width = (Bounds.InnerWidth - 2 * padding) * (1 - alarmValueRel), Height = Bounds.InnerHeight - 2 * padding
                };

                ctxStatic.SetSourceRGBA(0.62, 0, 0, 0.4);

                RoundRectangle(ctxStatic, Bounds.drawX + padding + insetWidth * alarmValueRel, Bounds.drawY + padding, insetWidth * (1 - alarmValueRel), insetHeight, GuiStyle.ElementBGRadius);
                ctxStatic.Fill();
            }


            /*** 2. Handle ***/
            ImageSurface surface = new ImageSurface(Format.Argb32, (int)handleWidth + 5, (int)handleHeight + 5);
            Context      ctx     = genContext(surface);

            ctx.SetSourceRGBA(1, 1, 1, 0);
            ctx.Paint();
            ctx.SetSourceRGBA(0, 0, 0, 0.5);
            RoundRectangle(ctx, 0, 0, handleWidth, handleHeight, GuiStyle.ElementBGRadius);
            ctx.Fill();
            surface.Blur(3);

            RoundRectangle(ctx, 0, 0, handleWidth, handleHeight, GuiStyle.ElementBGRadius);
            fillWithPattern(api, ctx, woodTextureName);

            EmbossRoundRectangleElement(ctx, 0, 0, handleWidth, handleHeight, false);

            generateTexture(surface, ref handleTextureId);
            ctx.Dispose();
            surface.Dispose();

            ComposeHoverTextElement();
        }
예제 #5
0
        private void ConstrainTextFlowPath(List <TextFlowPath> flowPath, double posY, RichTextComponentBase comp)
        {
            Rectangled rect         = comp.BoundsPerLine[0];
            EnumFloat  elementFloat = comp.Float;

            double x1 = elementFloat == EnumFloat.Left ? rect.Width + comp.PaddingRight : 0;
            double x2 = elementFloat == EnumFloat.Right ? Bounds.InnerWidth - rect.Width - comp.PaddingLeft : Bounds.InnerWidth;

            double remainingHeight = rect.Height;

            for (int i = 0; i < flowPath.Count; i++)
            {
                TextFlowPath tfp = flowPath[i];

                if (tfp.Y2 <= posY)
                {
                    continue;                 // we already passed this one
                }
                double hereX1 = Math.Max(x1, tfp.X1);
                double hereX2 = Math.Min(x2, tfp.X2);


                // Current bounds are taller, let's make a split and insert ours
                if (tfp.Y2 > posY + rect.Height)
                {
                    // Already more contrained, don't touch
                    if (x1 <= tfp.X1 && x2 >= tfp.X2)
                    {
                        continue;
                    }

                    if (i == 0)
                    {
                        // We're at the begining, so don't need a "before" element
                        flowPath[i] = new TextFlowPath(hereX1, posY, hereX2, posY + rect.Height);
                        flowPath.Insert(i + 1, new TextFlowPath(tfp.X1, posY + rect.Height, tfp.X2, tfp.Y2));
                    }
                    else
                    {
                        flowPath[i] = new TextFlowPath(tfp.X1, tfp.Y1, tfp.X2, posY);
                        flowPath.Insert(i + 1, new TextFlowPath(tfp.X1, posY + rect.Height, tfp.X2, tfp.Y2));
                        flowPath.Insert(i, new TextFlowPath(hereX1, posY, hereX2, posY + rect.Height));
                    }

                    remainingHeight = 0;
                    break;
                }
                else

                // Current bounds are shorter, let's update it
                {
                    flowPath[i].X1   = hereX1;
                    flowPath[i].X2   = hereX2;
                    remainingHeight -= tfp.Y2 - posY;
                }
            }

            if (remainingHeight > 0)
            {
                flowPath.Add(new TextFlowPath(x1, posY, x2, posY + remainingHeight));
            }
        }
예제 #6
0
        public void CalcHeightAndPositions()
        {
            Bounds.CalcWorldBounds();

            if (DebugLogging)
            {
                api.Logger.VerboseDebug("GuiElementRichtext: before bounds: {0}/{1}  w/h = {2},{3}", Bounds.absX, Bounds.absY, Bounds.OuterWidth, Bounds.OuterHeight);
            }

            double posX = 0;
            double posY = 0;

            List <int>          currentLine  = new List <int>();
            List <TextFlowPath> flowPathList = new List <TextFlowPath>();

            flowPathList.Add(new TextFlowPath(Bounds.InnerWidth));

            double lineHeight          = 0;
            double ascentHeight        = 0;
            RichTextComponentBase comp = null;

            for (int i = 0; i < Components.Length; i++)
            {
                comp = Components[i];

                bool didLineBreak = comp.CalcBounds(flowPathList.ToArray(), lineHeight, posX, posY);

                if (DebugLogging)
                {
                    api.Logger.VerboseDebug("GuiElementRichtext, add comp {0}, posY={1}, lineHeight={2}", i, posY, lineHeight);
                    api.Logger.VerboseDebug("GuiElementRichtext, Comp bounds 0 w/h: {0}/{1}", comp.BoundsPerLine[0].Width, comp.BoundsPerLine[0].Height);
                }


                posX += scaled(comp.PaddingLeft);

                if (comp.Float == EnumFloat.None)
                {
                    posX  = 0;
                    posY += Math.Max(lineHeight, comp.BoundsPerLine[0].Height) + (didLineBreak ? GuiElement.scaled(comp.UnscaledMarginTop) : 0);
                    posY  = Math.Ceiling(posY);

                    currentLine.Clear();
                    lineHeight   = 0;
                    ascentHeight = 0;
                    continue;
                }

                if (didLineBreak)
                {
                    lineHeight   = Math.Ceiling(Math.Max(lineHeight, comp.BoundsPerLine[0].Height));
                    ascentHeight = Math.Ceiling(Math.Max(ascentHeight, comp.BoundsPerLine[0].AscentOrHeight));

                    // All previous elements in this line might need to have their Y pos adjusted due to a larger element in the line
                    foreach (int index in currentLine)
                    {
                        RichTextComponentBase lineComp       = Components[index];
                        Rectangled            lastLineBounds = lineComp.BoundsPerLine[lineComp.BoundsPerLine.Length - 1];

                        if (lineComp.VerticalAlign == EnumVerticalAlign.Bottom)
                        {
                            lastLineBounds.Y = Math.Ceiling(lastLineBounds.Y + ascentHeight - lineComp.BoundsPerLine[lineComp.BoundsPerLine.Length - 1].AscentOrHeight);
                        }
                        if (lineComp.VerticalAlign == EnumVerticalAlign.Middle)
                        {
                            lastLineBounds.Y = Math.Ceiling(lastLineBounds.Y + ascentHeight - lineComp.BoundsPerLine[lineComp.BoundsPerLine.Length - 1].AscentOrHeight / 2);
                        }
                    }

                    // The current element that was still on the same line as well
                    // Offset all lines by the gained y-offset on the first line
                    if (comp.VerticalAlign == EnumVerticalAlign.Bottom)
                    {
                        foreach (var val in comp.BoundsPerLine)
                        {
                            val.Y = Math.Ceiling(val.Y + ascentHeight - comp.BoundsPerLine[0].AscentOrHeight);
                        }
                    }
                    if (comp.VerticalAlign == EnumVerticalAlign.Middle)
                    {
                        foreach (var val in comp.BoundsPerLine)
                        {
                            val.Y = Math.Ceiling(val.Y + ascentHeight - comp.BoundsPerLine[0].AscentOrHeight / 2);
                        }
                    }

                    currentLine.Clear();
                    currentLine.Add(i);


                    posY += lineHeight;
                    for (int k = 1; k < comp.BoundsPerLine.Length - 1; k++)
                    {
                        posY += comp.BoundsPerLine[k].Height;
                    }
                    posY += scaled(comp.UnscaledMarginTop);
                    posY  = Math.Ceiling(posY);


                    posX = comp.BoundsPerLine[comp.BoundsPerLine.Length - 1].Width; // + GuiElement.scaled(comp.PaddingLeft); - this adds too much padding when there is a line break inside a rich text compoment and afterwards there comes a link
                    if (comp.BoundsPerLine[comp.BoundsPerLine.Length - 1].Width > 0)
                    {
                        lineHeight   = comp.BoundsPerLine[comp.BoundsPerLine.Length - 1].Height;
                        ascentHeight = comp.BoundsPerLine[comp.BoundsPerLine.Length - 1].AscentOrHeight;
                    }
                    else
                    {
                        lineHeight   = 0;
                        ascentHeight = 0;
                    }
                }
                else
                {
                    if (comp.Float == EnumFloat.Inline && comp.BoundsPerLine.Length > 0)
                    {
                        posX        += comp.BoundsPerLine[0].Width;
                        lineHeight   = Math.Max(comp.BoundsPerLine[0].Height, lineHeight);
                        ascentHeight = Math.Max(comp.BoundsPerLine[0].AscentOrHeight, ascentHeight);
                        currentLine.Add(i);
                    }
                }

                if (comp.Float != EnumFloat.Inline)
                {
                    ConstrainTextFlowPath(flowPathList, posY, comp);
                }
            }


            if (DebugLogging)
            {
                api.Logger.VerboseDebug("GuiElementRichtext: after loop. posY = {0}", posY);
            }


            if (comp != null && posX > 0 && comp.BoundsPerLine.Length > 0)
            {
                posY += lineHeight;
            }

            Bounds.fixedHeight = (posY + 1) / RuntimeEnv.GUIScale;


            double maxHeight = 0;

            foreach (int index in currentLine)
            {
                RichTextComponentBase lineComp       = Components[index];
                Rectangled            lastLineBounds = lineComp.BoundsPerLine[lineComp.BoundsPerLine.Length - 1];
                maxHeight = Math.Max(maxHeight, lastLineBounds.Height);
            }

            foreach (int index in currentLine)
            {
                RichTextComponentBase lineComp       = Components[index];
                Rectangled            lastLineBounds = lineComp.BoundsPerLine[lineComp.BoundsPerLine.Length - 1];

                if (lineComp.VerticalAlign == EnumVerticalAlign.Bottom)
                {
                    lastLineBounds.Y = Math.Ceiling(lastLineBounds.Y + ascentHeight - lineComp.BoundsPerLine[lineComp.BoundsPerLine.Length - 1].AscentOrHeight);
                }
                if (lineComp.VerticalAlign == EnumVerticalAlign.Middle)
                {
                    lastLineBounds.Y = (maxHeight - lastLineBounds.Height) / 2f;
                }
            }

            this.flowPath = flowPathList.ToArray();

            if (DebugLogging)
            {
                api.Logger.VerboseDebug("GuiElementRichtext: after bounds: {0}/{1}  w/h = {2},{3}", Bounds.absX, Bounds.absY, Bounds.OuterWidth, Bounds.OuterHeight);
                api.Logger.VerboseDebug("GuiElementRichtext: posY = {0}", posY);

                api.Logger.VerboseDebug("GuiElementRichtext: framewidth/height: {0}/{1}", api.Render.FrameWidth, api.Render.FrameHeight);
            }
        }