amiga-mui/thebar

View on GitHub
mcp/utils.c

Summary

Maintainability
Test Coverage
/***************************************************************************

 TheBar.mcc - Next Generation Toolbar MUI Custom Class
 Copyright (C) 2003-2005 Alfonso Ranieri
 Copyright (C) 2005-2022 TheBar Open Source Team

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 TheBar class Support Site:  http://www.sf.net/projects/thebar

 $Id$

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

#include "class.h"

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

#ifndef MUIA_Backgroundadjust_DoParent
#define MUIA_Backgroundadjust_DoParent      0x80426a55 /* V20 i.. BOOL              */ /* private */
#endif

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

// DoSuperNew()
// Calls parent NEW method within a subclass
#if !defined(__MORPHOS__)
#ifdef __AROS__
Object * VARARGS68K DoSuperNew(struct IClass *cl, Object *obj, Tag tag1, ...)
{
    AROS_SLOWSTACKTAGS_PRE_AS(tag1, Object *)
    retval = (Object *)DoSuperMethod(cl, obj, OM_NEW, AROS_SLOWSTACKTAGS_ARG(tag1), NULL);
    AROS_SLOWSTACKTAGS_POST
}
#else
Object * VARARGS68K DoSuperNew(struct IClass *cl, Object *obj, ...)
{
  Object *rc;
  VA_LIST args;
  struct opSet msg;

  VA_START(args, obj);
  msg.MethodID = OM_NEW;
  msg.ops_AttrList = VA_ARG(args, struct TagItem *);
  msg.ops_GInfo = NULL;
  rc = (Object *)DoSuperMethodA(cl, obj, (Msg)&msg);
  VA_END(args);

  return rc;
}
#endif
#endif

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

#if !defined(__MORPHOS__) && !defined(__AROS__)
int stch_l(const char *chr_ptr,long *u_ptr)
{
    char *end_ptr;

    *u_ptr = strtoul(chr_ptr, &end_ptr, 16);

    return end_ptr - chr_ptr;
}
#endif

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

Object *
obutton(const void *text, const void *help)
{
    Object *obj;

    if((obj = MUI_MakeObject(MUIO_Button,(IPTR)tr(text))))
        SetAttrs(obj,MUIA_CycleChain,TRUE,MUIA_ShortHelp,(IPTR)tr(help),TAG_DONE);

    return obj;
}

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

Object *
ocycle(STRPTR *array, const void *key, const void *help)
{
    Object *obj;

    if((obj = MUI_MakeObject(MUIO_Cycle,(IPTR)tr(key),(IPTR)array)))
        SetAttrs(obj,MUIA_CycleChain,TRUE,MUIA_ShortHelp,(IPTR)tr(help),TAG_DONE);

    return obj;
}

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

Object *
ocheck(const void *key, const void *help)
{
    Object *obj;

    if((obj = MUI_MakeObject(MUIO_Checkmark,(IPTR)tr(key))))
        SetAttrs(obj,MUIA_CycleChain,TRUE,MUIA_ShortHelp,(IPTR)tr(help),TAG_DONE);

    return obj;
}

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

Object *
oslider(const void *key, const void *help, LONG min, LONG max)
{
    Object *obj;

    if((obj = MUI_MakeObject(MUIO_Slider,(IPTR)tr(key),min,max)))
        SetAttrs(obj,MUIA_CycleChain,TRUE,MUIA_ShortHelp,(IPTR)tr(help),TAG_DONE);

    return obj;
}

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

Object *
opop(ULONG type, const void *key)
{
    Object *obj;

    if (!(lib_flags & BASEFLG_MUI4) && (type==MUII_PopFont))
        type = MUII_PopUp;

    if((obj = MUI_MakeObject(MUIO_PopButton,type)))
    {
        set(obj,MUIA_CycleChain,TRUE);

        if (key)
        {
            ULONG k;

            if((k = getKeyChar(tr(key))))
                set(obj,MUIA_ControlChar,ToLower(k));
        }
    }

    return obj;
}

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

Object *
opoppen(const void *key, const void *title, const void *help)
{
    #if defined(__MORPHOS__) || defined(__amigaos4__) || defined(__AROS__)
    return PoppenObject,
        MUIA_Window_Title, (IPTR)tr(title),
        MUIA_ControlChar,  (ULONG)getKeyChar(tr(key)),
        MUIA_Draggable,    TRUE,
        MUIA_CycleChain,   TRUE,
        MUIA_ShortHelp,    (IPTR)tr(help),
        MUIA_FixHeight,    30,
    End;
    #else
    if (lib_flags & BASEFLG_MUI20)
    {
        return PoppenObject,
            MUIA_Window_Title, (ULONG)tr(title),
            MUIA_ControlChar,  (ULONG)getKeyChar(tr(key)),
            MUIA_Draggable,    TRUE,
            MUIA_CycleChain,   TRUE,
            MUIA_ShortHelp,    (ULONG)tr(help),
            MUIA_FixHeight,    30,
        End;
    }
    else
    {
        return poppenObject,
            MUIA_Window_Title, (ULONG)tr(title),
            MUIA_ControlChar,  (ULONG)getKeyChar(tr(key)),
            MUIA_Draggable,    TRUE,
            MUIA_CycleChain,   TRUE,
            MUIA_ShortHelp,    (ULONG)tr(help),
            MUIA_FixHeight,    30,
        End;
    }
    #endif
}

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

Object *
opopfri(const void *key, const void *title, const void *help)
{
    return MUI_NewObject("Popfrimage.mui",
        MUIA_Window_Title,      (IPTR)tr(title),
        MUIA_ControlChar,       (ULONG)getKeyChar(tr(key)),
        MUIA_CycleChain,        TRUE,
        MUIA_ShortHelp,         (IPTR)tr(help),
        MUIA_FixHeight,         30,
        MUIA_Framedisplay_Spec, NULL,
        MUIA_Imagedisplay_Spec, NULL,
        MUIA_Backgroundadjust_DoParent, TRUE,
        MUIA_FixHeight,         0,
    TAG_DONE);
}

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

Object *
opopback(UNUSED ULONG gradient, const void *key, const void *title, const void *help)
{
    #if defined(__MORPHOS__) || defined(__amigaos4__) || defined(__AROS__)
    return MUI_NewObject(MUIC_Popimage,
        MUIA_Imageadjust_Type, MUIV_Imageadjust_Type_Background,
        MUIA_Window_Title,     (IPTR)tr(title),
        MUIA_ControlChar,      (ULONG)getKeyChar(tr(key)),
        MUIA_Draggable,        TRUE,
        MUIA_CycleChain,       TRUE,
        MUIA_ShortHelp,        (IPTR)tr(help),
        MUIA_FixHeight,        0,
    TAG_DONE);
    #else
    if (lib_flags & BASEFLG_MUI20)
    {
        return MUI_NewObject(MUIC_Popimage,
            MUIA_Imageadjust_Type, MUIV_Imageadjust_Type_Background,
            MUIA_Window_Title,     (ULONG)tr(title),
            MUIA_ControlChar,      (ULONG)getKeyChar(tr(key)),
            MUIA_Draggable,        TRUE,
            MUIA_CycleChain,       TRUE,
            MUIA_ShortHelp,        (ULONG)tr(help),
            MUIA_FixHeight,        0,
        TAG_DONE);
    }
    else
    {
        return popbackObject,
            MUIA_Window_Title,           (ULONG)tr(title),
            MUIA_ControlChar,            (ULONG)getKeyChar(tr(key)),
            MUIA_Draggable,              TRUE,
            MUIA_CycleChain,             TRUE,
            MUIA_ShortHelp,              (ULONG)tr(help),
            MUIA_Popbackground_Gradient, gradient,
            MUIA_FixHeight,              0,
        End;
    }
    #endif
}

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

#ifndef PopframeObject
#define PopframeObject MUI_NewObject(MUIC_Popframe
#endif

Object *
opopframe(const void *key, const void *title, const void *help)
{
    return PopframeObject,
        MUIA_Window_Title, (IPTR)tr(title),
        MUIA_Draggable,    TRUE,
        MUIA_CycleChain,   1,
        MUIA_ShortHelp,    (IPTR)tr(help),
        MUIA_ControlChar,  (ULONG)getKeyChar(tr(key)),
        MUIA_FixHeight,    0,
    End;
}

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

#if defined(__amigaos3__)
void drawGradient(Object *obj, struct MUIS_TheBar_Gradient *grad)
{
    struct RastPort *rp;
    ULONG           rs, gs, bs, horiz, from, to;
    int             i, x, d, step, rdif, gdif, bdif, r1, g1, b1, r2, g2, b2, r, g, b, rd, gd, bd, ridx, gidx, bidx;
    UWORD           l = _mleft(obj), t = _mtop(obj), w = _mwidth(obj), h = _mheight(obj);

    rd = rdif= ridx = gd = gidx = bd = bidx = 0;

    rp = _rp(obj);

    from  = grad->from;
    to    = grad->to;
    horiz = grad->flags & MUIV_TheBar_Gradient_Horiz;

    /* Compute diffs */
    r1 = (from & 0x00FF0000)>>16;
    g1 = (from & 0x0000FF00)>>8;
    b1 = (from & 0x000000FF);

    r2 = (to & 0x00FF0000)>>16;
    g2 = (to & 0x0000FF00)>>8;
    b2 = (to & 0x000000FF);

    if (r1>r2)
    {
        rdif = r1-r2;
        rs = FALSE;
    }
    else
    {
        rdif = r2-r1;
        rs = TRUE;
    }

    if (g1>g2)
    {
        gdif = g1-g2;
        gs = FALSE;
    }
    else
    {
        gdif = g2-g1;
        gs = TRUE;
    }

    if (b1>b2)
    {
        bdif = b1-b2;
        bs = FALSE;
    }
    else
    {
        bdif = b2-b1;
        bs = TRUE;
    }

    /* Find out max diff */
    step = (rdif>=gdif) ? rdif : gdif;
    if (bdif>step) step = bdif;

    /* Find out best step to minimize rest */
    if (horiz)
    {
        if (step>w) step = w;

        if (step==0) step = 1;
        else
        {
            x = w/step;
            if (w!=x*step)
            {
                step = w/(x+1);
                if (step>w) step = w;
            }
        }
    }
    else
    {
        if (step>h) step = h;

        if (step==0) step = 1;
        else
        {
            x = h/step;
            if (h!=x*step)
            {
                step = h/(x+1);
                if (step>h) step = h;
            }
        }
    }

    if (step>1)
    {
        /* Compute color components deltas */
        rd = rdif/step;
        if (!rd) rd = 1;

        gd = gdif/step;
        if (!gd) gd = 1;

        bd = bdif/step;
        if (!bd) bd = 1;

        /* Compute rests */
        ridx = (rdif>step) ? step/((rdif-step)/rd) : 0;
        gidx = (gdif>step) ? step/((gdif-step)/gd) : 0;
        bidx = (bdif>step) ? step/((bdif-step)/bd) : 0;
    }

    /* Here we go */
    d = (horiz) ? w/step : h/step;
    x = (horiz) ? l : t;
    r = r1;
    g = g1;
    b = b1;

    for (i = 0; i<step; i++)
    {
        ULONG col = (r<<16) | (g<<8) | b;

        /* Fill; if last step fill all rest */
        if (horiz)
            if (i==step-1)
            {
                FillPixelArray(rp,x,t,w-x+l,h,col);
                break;
            }
            else FillPixelArray(rp,x,t,d,h,col);
        else
            if (i==step-1)
            {
                FillPixelArray(rp,l,x,w,h-x+t,col);
                break;
            }
            else FillPixelArray(rp,l,x,w,d,col);

        x += d;

        /* Add delta to each color component */
        if (rs)
        {
            r += rd;

            /* Time to add more one more delta? */
            if (i && ridx && !(i%ridx)) r += rd;
            if (r>r2) r = r2;
        }
        else
        {
            r -= rd;

            if (i && ridx && !(i%ridx)) r -= rd;
            if (r<r2) r = r2;
        }

        if (gs)
        {
            g += gd;

            if (i && gidx && !(i%gidx)) g += gd;
            if (g>g2) g = g2;
        }
        else
        {
            g -= gd;

            if (i && gidx && !(i%gidx)) g -= gd;
            if (g<g2) g = g2;
        }

        if (bs)
        {
            b += bd;

            if (i && bidx && !(i%bidx)) b += bd;
            if (b>b2) b = b2;
        }
        else
        {
            b -= bd;

            if (i && bidx && !(i%bidx)) b -= bd;
            if (b<b2) b = b2;
        }
    }
}
#endif

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

ULONG getKeyChar(const char *string)
{
    ULONG res = 0;

    if (string)
    {
        for (; *string && *string!='_'; string++);
        if (*string++)
            res = ToLower(*string);
    }

    return res;
}

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