root/src/apps/devices/ResourceUsageWindow.cpp
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
//
//      Copyright (c) 2003-2004, Haiku
//
//  This software is part of the Haiku distribution and is covered
//  by the MIT License.
//
//
//  File:        ResourceUsageWindow.cpp
//  Author:      Sikosis, Jérôme Duval
//  Description: Devices Preferences
//  Created :    July 19, 2003
// 
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~


// Includes ------------------------------------------------------------------
#include <Box.h>
#include <Catalog.h>
#include <Screen.h>
#include <ScrollView.h>
#include <stdio.h>
#include <strings.h>
#include <TabView.h>

#include "DevicesInfo.h"
#include "DevicesWindows.h"

#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "ResourceUsageWindow"

class IRQDMAItem : public BListItem
{
        public:
                IRQDMAItem(int32 number, const char* name);
                ~IRQDMAItem();
                virtual void DrawItem(BView *, BRect, bool = false);
        private:
                char* fName;
                int32 fNumber;
};


IRQDMAItem::IRQDMAItem(int32 number, const char* name)
        : BListItem(),
        fNumber(number)
{
        fName = strdup(name);
}

IRQDMAItem::~IRQDMAItem()
{
        free(fName);
}

/***********************************************************
 * DrawItem
 ***********************************************************/
void
IRQDMAItem::DrawItem(BView *owner, BRect itemRect, bool complete)
{
        rgb_color kBlack = { 0,0,0,0 };
        rgb_color kHighlight = { 156,154,156,0 };
        
        if (IsSelected() || complete) {
                rgb_color color;
                if (IsSelected())
                        color = kHighlight;
                else
                        color = owner->ViewColor();
                
                owner->SetHighColor(color);
                owner->SetLowColor(color);
                owner->FillRect(itemRect);
                owner->SetHighColor(kBlack);
                
        } else {
                owner->SetLowColor(owner->ViewColor());
        }
        
        BFont font = be_plain_font;
        font_height     finfo;
        font.GetHeight(&finfo);
        
        BPoint point = BPoint(itemRect.left + 5, itemRect.bottom - finfo.descent + 1);
        
        owner->SetHighColor(kBlack);
        owner->SetFont(be_plain_font);
        owner->MovePenTo(point);
        if (fNumber > -1) {
                char string[2];
                sprintf(string, "%ld", fNumber);
                owner->DrawString(string);
        }
        point += BPoint(28, 0);
        owner->MovePenTo(point);
        owner->DrawString(fName);
}

class RangeItem : public BListItem
{
        public:
                RangeItem(uint32 lowAddress, uint32 highAddress, const char* name);
                ~RangeItem();
                virtual void DrawItem(BView *, BRect, bool = false);
                static int Compare(const void *firstArg, const void *secondArg);
        private:
                char* fName;
                uint32 fLowAddress, fHighAddress;
};


RangeItem::RangeItem(uint32 lowAddress, uint32 highAddress, const char* name)
        : BListItem(),
        fLowAddress(lowAddress), 
        fHighAddress(highAddress)
{
        fName = strdup(name);
}

RangeItem::~RangeItem()
{
        free(fName);
}

/***********************************************************
 * DrawItem
 ***********************************************************/
void
RangeItem::DrawItem(BView *owner, BRect itemRect, bool complete)
{
        rgb_color kBlack = { 0,0,0,0 };
        rgb_color kHighlight = { 156,154,156,0 };
        
        if (IsSelected() || complete) {
                rgb_color color;
                if (IsSelected())
                        color = kHighlight;
                else
                        color = owner->ViewColor();
                
                owner->SetHighColor(color);
                owner->SetLowColor(color);
                owner->FillRect(itemRect);
                owner->SetHighColor(kBlack);
                
        } else {
                owner->SetLowColor(owner->ViewColor());
        }
        
        BFont font = be_plain_font;
        font_height     finfo;
        font.GetHeight(&finfo);
        
        BPoint point = BPoint(itemRect.left + 17, itemRect.bottom - finfo.descent + 1);
        owner->SetFont(be_fixed_font);
        owner->SetHighColor(kBlack);
        owner->MovePenTo(point);
        
        if (fLowAddress >= 0) {
                char string[255];
                sprintf(string, "0x%04lx - 0x%04lx", fLowAddress, fHighAddress);
                owner->DrawString(string);
        }
        point += BPoint(174, 0);
        owner->SetFont(be_plain_font);
        owner->MovePenTo(point);
        owner->DrawString(fName);
}

int 
RangeItem::Compare(const void *firstArg, const void *secondArg)
{
        const RangeItem *item1 = *static_cast<const RangeItem * const *>(firstArg);
        const RangeItem *item2 = *static_cast<const RangeItem * const *>(secondArg);
        
        if (item1->fLowAddress < item2->fLowAddress) {
                return -1;
        } else if (item1->fLowAddress > item2->fLowAddress) {
                return 1;
        } else 
                return 0;

}


// ----------------------------------------------------------------------------


// ResourceUsageWindow - Constructor
ResourceUsageWindow::ResourceUsageWindow(BRect frame, BList &list) 
        : BWindow (frame, B_TRANSLATE("Resource Usage"), B_TITLED_WINDOW_LOOK,
                B_NORMAL_WINDOW_FEEL , B_NOT_ZOOMABLE|B_NOT_RESIZABLE)
{
        InitWindow(list);
        CenterOnScreen();
        Show();
}
// ----------------------------------------------------------------------------


// ResourceUsageWindow - Destructor
ResourceUsageWindow::~ResourceUsageWindow()
{
        
}
// ----------------------------------------------------------------------------


// ResourceUsageWindow::InitWindow -- Initialization Commands here
void ResourceUsageWindow::InitWindow(BList &list)
{
        BRect rtab = Bounds();
        BRect rlist = Bounds();
        rtab.top += 10;
        rlist.top += 10;
        rlist.left += 12;
        rlist.right -= 15 + B_V_SCROLL_BAR_WIDTH;
        rlist.bottom -= 47;

        // Create the TabView and Tabs
        BTabView *tabView = new BTabView(rtab,"resource_usage_tabview");
        tabView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
        
        rtab = tabView->Bounds();
        rtab.InsetBy(5,5);
        
        // Create the ListViews
        BListView *IRQListView = new BListView(rlist, "IRQListView",
                B_SINGLE_SELECTION_LIST, B_FOLLOW_LEFT | B_FOLLOW_TOP,
                B_WILL_DRAW | B_NAVIGABLE);
        BListView *DMAListView = new BListView(rlist, "DMAListView",
                B_SINGLE_SELECTION_LIST, B_FOLLOW_LEFT | B_FOLLOW_TOP,
                B_WILL_DRAW | B_NAVIGABLE);
        BListView *IORangeListView = new BListView(rlist, "IORangeListView",
                B_SINGLE_SELECTION_LIST, B_FOLLOW_LEFT | B_FOLLOW_TOP,
                B_WILL_DRAW | B_NAVIGABLE);
        BListView *memoryListView = new BListView(rlist, "memoryListView",
                B_SINGLE_SELECTION_LIST, B_FOLLOW_LEFT | B_FOLLOW_TOP,
                B_WILL_DRAW | B_NAVIGABLE);
        
        BScrollView *IRQScrollView = new BScrollView("scroll_list1", IRQListView,
                B_FOLLOW_LEFT|B_FOLLOW_TOP, 0, false, true, B_FANCY_BORDER);
        BScrollView *DMAScrollView = new BScrollView("scroll_list2", DMAListView,
                B_FOLLOW_LEFT|B_FOLLOW_TOP, 0, false, true, B_FANCY_BORDER);
        BScrollView *IORangeScrollView = new BScrollView("scroll_list3",
                IORangeListView, B_FOLLOW_LEFT|B_FOLLOW_TOP, 0, false, true,
                B_FANCY_BORDER);
        BScrollView *memoryScrollView = new BScrollView("scroll_list4",
                memoryListView, B_FOLLOW_LEFT|B_FOLLOW_TOP, 0, false, true,
                B_FANCY_BORDER);
        
        BTab *tab = new BTab();
        tabView->AddTab(IRQScrollView, tab);
        tab->SetLabel(B_TRANSLATE("IRQ"));
        tab = new BTab();
        tabView->AddTab(DMAScrollView, tab);
        tab->SetLabel(B_TRANSLATE("DMA"));
        tab = new BTab();
        tabView->AddTab(IORangeScrollView, tab);
        tab->SetLabel(B_TRANSLATE("IO Range"));
        tab = new BTab();
        tabView->AddTab(memoryScrollView, tab);
        tab->SetLabel(B_TRANSLATE("Memory Range"));
        
        {
                uint32 mask = 1;
                
                for (int i=0;i<16;mask<<=1,i++) {
                        bool first = true;
                        
                        for (int32 j=0; j<list.CountItems(); j++) {
                                DevicesInfo *deviceInfo = (DevicesInfo *)list.ItemAt(j);
                                struct device_configuration *current = deviceInfo->GetCurrent();
                                resource_descriptor r;
                                
                                int32 num = count_resource_descriptors_of_type(current,
                                        B_IRQ_RESOURCE);
                                
                                for (int32 k=0;k<num;k++) {
                                        get_nth_resource_descriptor_of_type(current, k, B_IRQ_RESOURCE,
                                                        &r, sizeof(resource_descriptor));
                                        
                                        if (mask & r.d.m.mask) {
                                                IRQListView->AddItem(new IRQDMAItem(first ? i : -1,
                                                        deviceInfo->GetCardName()));
                                                first = false;
                                        }
                                }
                        }
                        
                        if (first) {
                                IRQListView->AddItem(new IRQDMAItem(i, ""));
                        }
                }
        }
        
        {
                uint32 mask = 1;
                
                for (int i=0;i<8;mask<<=1,i++) {
                        bool first = true;
                        
                        for (int32 j=0; j<list.CountItems(); j++) {
                                DevicesInfo *deviceInfo = (DevicesInfo *)list.ItemAt(j);
                                struct device_configuration *current = deviceInfo->GetCurrent();
                                resource_descriptor r;
                                
                                int32 num = count_resource_descriptors_of_type(current,
                                        B_DMA_RESOURCE);
                                
                                for (int32 k=0;k<num;k++) {
                                        get_nth_resource_descriptor_of_type(current, k,
                                                B_DMA_RESOURCE, &r, sizeof(resource_descriptor));
                                        
                                        if (mask & r.d.m.mask) {
                                                DMAListView->AddItem(new IRQDMAItem(first ? i : -1,
                                                        deviceInfo->GetCardName()));
                                                first = false;
                                        }
                                }
                        }
                        
                        if (first) {
                                DMAListView->AddItem(new IRQDMAItem(i, ""));
                        }
                }
        }

        {
                for (int32 j=0; j<list.CountItems(); j++) {
                        DevicesInfo *deviceInfo = (DevicesInfo *)list.ItemAt(j);
                        struct device_configuration *current = deviceInfo->GetCurrent();
                        resource_descriptor r;
                        
                        int32 num = count_resource_descriptors_of_type(current,
                                B_IO_PORT_RESOURCE);
                        
                        for (int32 k=0;k<num;k++) {
                                get_nth_resource_descriptor_of_type(current, k,
                                        B_IO_PORT_RESOURCE,     &r, sizeof(resource_descriptor));
                                
                                IORangeListView->AddItem(new RangeItem(r.d.r.minbase, 
                                        r.d.r.minbase + r.d.r.len - 1, deviceInfo->GetCardName()));
                        }
                }
        
                IORangeListView->SortItems(&RangeItem::Compare);
        }
        
        {
                for (int32 j=0; j<list.CountItems(); j++) {
                        DevicesInfo *deviceInfo = (DevicesInfo *)list.ItemAt(j);
                        struct device_configuration *current = deviceInfo->GetCurrent();
                        resource_descriptor r;
                        
                        int32 num = count_resource_descriptors_of_type(current,
                                B_MEMORY_RESOURCE);
                        
                        for (int32 k=0;k<num;k++) {
                                get_nth_resource_descriptor_of_type(current, k, B_MEMORY_RESOURCE,
                                                &r, sizeof(resource_descriptor));
                                
                                memoryListView->AddItem(new RangeItem(r.d.r.minbase, 
                                        r.d.r.minbase + r.d.r.len - 1, deviceInfo->GetCardName()));
                        }
                }
        
                memoryListView->SortItems(&RangeItem::Compare);
        }
        
        
        BBox *background = new BBox(Bounds(), "background");
        background->SetBorder(B_NO_BORDER);
        AddChild(background);
        background->AddChild(tabView);
}
// ----------------------------------------------------------------------------


// ResourceUsageWindow::MessageReceived -- receives messages
void 
ResourceUsageWindow::MessageReceived (BMessage *message)
{
        switch(message->what)
        {
                default:
                        BWindow::MessageReceived(message);
                        break;
        }
}
// ----------------------------------------------------------------------------