Математика перерисовки виджетов
От: ShubinEV Россия http://erladvisor.blogspot.de/
Дата: 22.01.10 09:56
Оценка:
Я накладываю различные графические элементы(виджеты) поверх видео. При изменении разрешения видео необходимо менять размер и расположение виджетов. Раньше мне приходилось программировать графический интерфейс на Qt. Там реализована математика перерисовки дочерних виджетов при растягивании главного окна. В Qt гибкие настройки поведения виджетов. Существуют ли библиотеки в которых реализована математика без графических элементов или мне нужно ковырять код Qt. Проект разрабатывается на C++ под Linux.
перерисовка виджетов
Re: Математика перерисовки виджетов
От: ShaggyOwl Россия http://www.rsdn.org
Дата: 24.01.10 14:59
Оценка: 1 (1)
Здравствуйте, ShubinEV, Вы писали:

SEV>Я накладываю различные графические элементы(виджеты) поверх видео. При изменении разрешения видео необходимо менять размер и расположение виджетов. Раньше мне приходилось программировать графический интерфейс на Qt. Там реализована математика перерисовки дочерних виджетов при растягивании главного окна. В Qt гибкие настройки поведения виджетов. Существуют ли библиотеки в которых реализована математика без графических элементов или мне нужно ковырять код Qt. Проект разрабатывается на C++ под Linux.


Сочувствую.
Что можно посмотреть:
http://en.wikipedia.org/wiki/Layout_engine
http://en.wikipedia.org/wiki/List_of_layout_engines
http://en.wikipedia.org/wiki/Comparison_of_layout_engines

На рсдн есть форум посвященный HTMLayout http://www.rsdn.ru/forum/htmlayout/, автора библиотеки зовут c-smile http://www.rsdn.ru/Users/13953.aspx, возможно он сумеет что-то подсказать.
Хорошо там, где мы есть! :)
Re: Математика перерисовки виджетов
От: alxn1 Россия  
Дата: 13.02.10 15:40
Оценка: 14 (1)
Здравствуйте, ShubinEV, Вы писали:

SEV>Я накладываю различные графические элементы(виджеты) поверх видео. При изменении разрешения видео необходимо менять размер и расположение виджетов. Раньше мне приходилось программировать графический интерфейс на Qt. Там реализована математика перерисовки дочерних виджетов при растягивании главного окна. В Qt гибкие настройки поведения виджетов. Существуют ли библиотеки в которых реализована математика без графических элементов или мне нужно ковырять код Qt. Проект разрабатывается на C++ под Linux.


Если не найдете что-нибудь готового и подходящего, то я бы рекомендовал бы посмотреть на то, как это сделано у Apple в Cocoa. Оно, правда, на Objective-C, но зато там довольно простой механизм, и его просто будет повторить. Смысл в том, что у каждого виджета (там оно NSView назвается) есть свойство autoresizingMask (типа int), являющееся комбинацией флагов:

enum {
NSViewNotSizable     = 0,
NSViewMinXMargin     = 1,
NSViewWidthSizable   = 2,
NSViewMaxXMargin     = 4,
NSViewMinYMargin     = 8,
NSViewHeightSizable  = 16,
NSViewMaxYMargin     = 32
};


Флаги означают, что надо масштабировать пропорционально ширину (NSViewWidthSizable), высоту (NSViewHeightSizable), расстояние от левого края родителя до виджета (NSViewMinXMargin) и так далее (подробнее можно доку у apple почитать или посмотреть на код ниже внимательно).

Далее, при изменении размера виджета-контейнера (не всегда, правда, а только если это разрешено, но это не так важно), контейнер вызывает у каждого виджета, который он содержит, метод
 - ( void ) resizeWithOldSuperviewSize: ( NSSize ) oldSize
. Вот код этого метода, выдранный из исходников GNUStep:


- (void) resizeWithOldSuperviewSize:(NSSize)oldSize        
{ // does not call setFrame: or setFrameSize:!
    float change, changePerOption;
    NSSize old_size = _frame.size;
    NSSize superViewFrameSize;    // super_view should not be nil!
    BOOL changedOrigin = NO;
    BOOL changedSize = NO;
    int options = 0;
    if(!super_view)
        return;    // how can this happen? We are called as [[sub_views objectAtIndex:i] resizeWithOldSuperviewSize: oldSize]
    superViewFrameSize = [super_view frame].size;    // super_view should not be nil!
    if(NSEqualSizes(oldSize, superViewFrameSize))
        return;    // ignore unchanged superview size
#if 0
    NSLog(@"resizeWithOldSuperviewSize %x: %@ -> %@ %@", _v.autoresizingMask, NSStringFromSize(oldSize), NSStringFromSize(superViewFrameSize), self);
#endif
    // do nothing if view is not resizable
    if(_v.autoresizingMask == NSViewNotSizable) 
        return;                                            
                                                        // determine if and how
    if(_v.autoresizingMask & NSViewWidthSizable)        // the X axis can be
        options++;                                        // resized 
    if(_v.autoresizingMask & NSViewMinXMargin)                
        options++;
    if(_v.autoresizingMask & NSViewMaxXMargin)                
        options++;
                                                        // adjust the X axis if
    if(options > 0)                                        // any X options are
        {                                                // set in the mask
        change = superViewFrameSize.width - oldSize.width;
        if(change != 0.0)
            {
            changePerOption = change / options;        
            
            if(_v.autoresizingMask & NSViewWidthSizable)        
                {        
                float oldFrameWidth = _frame.size.width;
                
                _frame.size.width += changePerOption;
                // NSWidth(frame) = MAX(0, NSWidth(frame) + changePerOption);
                if (NSWidth(_frame) <= 0)
                    {
                    NSAssert((NSWidth(_frame) <= 0), @"View frame width <= 0!");
                    NSLog(@"resizeWithOldSuperviewSize: View frame width <= 0!");
                    _frame.size.width = 0;
                    }
                if(_v.isRotatedFromBase)
                    {
                    _bounds.size.width *= _frame.size.width / oldFrameWidth;    // keep proportion
                                                                                //                _bounds.size.width = floor(_bounds.size.width);
                    }
                else
                    _bounds.size.width += changePerOption;
                changedSize = YES;
                }
            if(_v.autoresizingMask & NSViewMinXMargin)
                {
                _frame.origin.x += changePerOption;
                changedOrigin = YES;
                }
            }
        }
                                                        // determine if and how 
    options = 0;                                        // the Y axis can be
    if(_v.autoresizingMask & NSViewHeightSizable)        // resized    
        options++;                                        
    if(_v.autoresizingMask & NSViewMinYMargin)                
        options++;
    if(_v.autoresizingMask & NSViewMaxYMargin)                
        options++;
                                                        // adjust the Y axis if
    if(options > 0)                                    // any Y options are  
        {                                                // set in the mask
        change = superViewFrameSize.height - oldSize.height;
        if(change != 0.0)
            {
            changePerOption = change/options;        
            
            if(_v.autoresizingMask & NSViewHeightSizable)        
                {                                            
                float oldFrameHeight = _frame.size.height;
                
                _frame.size.height += changePerOption;
                if(NSHeight(_frame) <= 0)
                    {
                    NSLog(@"resizeWithOldSuperviewSize: View frame height <= 0!");
                    _frame.size.height = 0;
                    }
                if(_v.isRotatedFromBase)            
                    { // rotated
                    _bounds.size.height *= _frame.size.height/oldFrameHeight;
                    //                _bounds.size.height = floor(_bounds.size.height);
                    }
                else
                    { // normal
//                    if([super_view isFlipped])
//                        _bounds.size.height -= changePerOption;
//                    else
                        _bounds.size.height += changePerOption;
                    }
                changedSize = YES;
                }
            if([super_view isFlipped])
                {
                if((_v.autoresizingMask & NSViewMaxYMargin))
                    {                
                    _frame.origin.y += changePerOption;
                    changedOrigin = YES;
                    }
                }
            else
                {
                if((_v.autoresizingMask & NSViewMinYMargin))
                    {                
                    _frame.origin.y += changePerOption;
                    changedOrigin = YES;
                    }
                }
            }
        }
    if(changedSize || changedOrigin)
        { // we could call [self setFrameSize:] but that isn't done on AppKit
        [self _invalidateCTM];    // update when needed
        if(_v.isRotatedFromBase)    
            {
            float sx = _frame.size.width / _bounds.size.width;
            float sy = _frame.size.height / _bounds.size.height;
            // FIXME: should we scale old_size?
            NSLog(@"and now? %@", self);
            }
        [self resizeSubviewsWithOldSize: old_size];    // recursively go down
        if(_v.postFrameChange)
            [[NSNotificationCenter defaultCenter] postNotificationName:NOTICE(FrameDidChange) object: self];
        }
}


Прошу прощения, я ничего форматировать и переписывать не стал, лень Смысл этого кода в том, что дочерний виджет пересчитает свое положение и размер исходя из набора флагов в свойстве autoresizingMask, нового и старого размера виджета-контейнера. Кроме того, он (в случае, если он тоже контейнер) вызовет этот метод у виджетов, которые он сожержит ( [ self resizeSubviewsWithOldSize: old_size ]; ). Небольшая такая рекурсия

Формулы не сложные, тормозить ничего толком не должно. Правда, непривычно сначала (очень сильно от Qt, Gtk и прочего отличается), но, если привыкнуть — то вполне удобно.

PS: еще раз прошу прощения, теперь за Objective-C, на C++ совсем лень это переписывать
Re[2]: Математика перерисовки виджетов
От: alxn1 Россия  
Дата: 13.02.10 15:48
Оценка:
А, да. Если будете брать этот код за основу, то вам надо знать, что в Cocoa за начало координат взят левый-нижний угол и y-координата изменяется снизу-вверх (ось y направлена снизу-вверх). А метод — ( BOOL ) isFlipped; у NSView переворачивает эту ось. Хотя, по-большей части на формулы это и не должно влиять, вроде бы.
Re: Математика перерисовки виджетов
От: dilmah США  
Дата: 16.02.10 15:50
Оценка: 19 (1)
можно еще взглянуть http://en.wikipedia.org/wiki/Scwm
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.