Июнь 1st, 2010 от graann

Танцы с бубном, описанные в прошлом посте не актуальны для SDK 3.5 и выше :)

Март 30th, 2010 от graann

В ходе работы с пиккером, мы столкнулись с его неприятной особенностью: при попытке заменить предустановленный цвет пиккера на черный (самый первый элемент таблицы пиккера) контролл аккуратно закрывался, но и только. Т.е событие change не диспатчилось и текущий цвет не менялся.

В чем же проблема?

У стандартного пиккера предустановлена коллекция отображаемых в таблице цветов. Она передается в дата провайдер и содержит в себе 240 цветовых квадратов. Отображаемые в таблице цвета можно регулировать путем замены или модификации этой коллекции.

Для управления выбранным цветом контролла предусмотрено 2 свойства: selectedIndex selectedColor. Очевидно что selectedIndex — индекс цвета в коллекции дата провайдера. А вот с selectedColor все не так однозначно. При всем изобилии, таблица пиккера не вмещает в себя все могущие прийти в голову дизайнера цвета. И, когда вы пытаетесь в качестве selectedColor указатиь пиккеру значение отсутствующее в коллекции дата провайдера, происходит следующее.

* selectedColor устанавливается в заданный цвет
* В дата провайдере осуществляется поиск индекса итема содержащего этот цвет.
* Если такой итем найден, в selectedIndex прописывается соответствующее значение.
* Если же в дата провайдере отсутствует данный цвет, selectedIndex не изменяется.

Следует отметить, что по умолчанию selectedIndex и selectedColor выставлены в 0. Т.е когда мы пытаемся установить selectedColor в цвет отсутствующий в коллекции, selectedIndex не меняется и остается равным 0. В момент же интерактивного выбора нужного цвета в пиккере на каком-то из этапов осуществляется проверка соответствия индекса выбираемого значения текущему. Если значения совпадают, ничего не происходит. Отсюда и этот прекрасный баг. В selectedIndex-е пиккера прямо указано, что цвет у нас черный. А вот значение selectedColor при этом совершенно никого не волнует

Что делать?

Решение очевидно. Надо добавить в коллекцию дата провайдера недостающий цвет.

Вот так выглядит стандартный пиккер

Так он будет выглядеть если добавить новый цвет в конец коллекции.

Не слишком симпатично. Поэтому я предлагаю обратить внимание на второй столбец цветовой палитры. Он совершенно черный. Нехитрые исследования предустановленной коллекции дата провайдера показали, что перед нами столбец нулевых значений.

Для чего он, мне понять не удалось. А раз так, ничто не мешает добавлять в него новые цвета.

Нулевые элементы палитры начинаются с 1 индекса и повторяются через каждые 20, вплоть до 221 индекса.

Все что нужно это:
* Проверить значение selectedIndex после установки selectedColor.
* Если индекс не изменился, ищем первый нулевой элемент коллекции и присваиваем ему значение нового цвета.
* Если нулевые значения кончились добавляем новый цвет в конец коллекции.

Ниже код и превью результата

Code:

package
{
  import mx.collections.ListCollectionView;
  import mx.controls.ColorPicker;
 
  public class ChartColorPicker extends ColorPicker
  {
    public function ChartColorPicker()
    {
      super();
    }
    
      override public function set selectedColor(value:uint):void
      {
        
        if(dp && !dp.contains(value))
        {
          var ind: int = findFirstEmptyItemIndex();
          if(ind == -1) dp.addItem(value);
          else dp.setItemAt(value, ind);
        }
        super.selectedColor = value;
      }     
      
      private function get dp(): ListCollectionView
      {
        if( dataProvider is ListCollectionView) return dataProvider as ListCollectionView;
        else return null;
      }
      
      private const FIRST_EMPTY_INDEX: int = 1;
      private const EMPTY_INDEX_SHIFT: int = 20;
      
      private function findFirstEmptyItemIndex(): int
      {
        if(!dp) return -1;
        
        for(var i: int = FIRST_EMPTY_INDEX; i<dp.length; i+=EMPTY_INDEX_SHIFT)
        {
          if(dp.getItemAt(i) == 0)
          {
            return i;
          }
        }
        return -1;
      }
  }
}
Март 25th, 2008 от graann

Константин Ковалев предложил более простой и изящный вариант решения проблемы затронутой мною в предыдущем посте.

Суть решения заключается в использовании метатега RemoteClass в классе сохраняемого объекта. Т.е registerClassAlias не требуется. Код ниже:

XML:

<mx:Application
  creationComplete="onCreationComplete()"
  xmlns:mx="http://www.adobe.com/2006/mxml"
  layout="vertical">
  <mx:Script>
    <![CDATA[
      import com.riapriority.tests.DataObject;
      
      private var so:SharedObject;
      private var dataObject:DataObject;
  
  
      private function onCreationComplete(): void
      {
        dataObject = new DataObject();
        so = SharedObject.getLocal ("test");
      }
  
  
      private function dataObjectGeneration (): void
      {
        dataObject.generate();
        ta.text += 'GENERATING: ' + dataObject.toString() + '\n';
      }
  
      private function saveLocalData(): void
      {
        so.data.DataObject = dataObject;
        so.flush();
        ta.text += 'SAVE: ' + dataObject.toString() + '\n';
      }
  
      private function loadLocalData(): void
      {
        so = SharedObject.getLocal('test');
        if(so.data.DataObject != null)
        {
          dataObject = so.data.DataObject as DataObject;
          ta.text += 'LOAD: ' + dataObject.toString() + '\n';
        }
        else
        {
          ta.text += 'LOAD: null\n';
        }
      }
    ]]>
  </mx:Script>
  
  <mx:Button
    label="Generate"
    click="{dataObjectGeneration()}"/>
  <mx:Button
    label="Save"
    click="{saveLocalData()}"/>
  <mx:Button
    label="Load"
    click="{loadLocalData()}"/>
  <mx:TextArea
    width="50%"
    height="50%"
    id="ta"/>
</mx:Application>

и код класса

  1. package com.riapriority.tests
  2. {
  3.         import mx.formatters.DateFormatter;
  4.        
  5.         [Bindable]
  6.         [RemoteClass(alias="com.riapriority.tests.DataObject")]
  7.         public class DataObject
  8.         {
  9.                 public var date: Date;
  10.                 public var random: String;
  11.  
  12.                 public function generate(): void
  13.                 {
  14.                         date = new Date();
  15.                         random = "" + Math.random() * 10000;
  16.                 }
  17.  
  18.                 public function toString():String
  19.                 {
  20.                         var df:DateFormatter = new DateFormatter ();
  21.                         df.formatString = "JJ:NN:SS DD/MM/YYYY";
  22.                         return "\n  date: " + df.format(date) + "\n  random: " + random;
  23.                 }
  24.         }
  25. }

[Bindable] здесь не обязателен, но как тонко выразился Константин,
класс без [Bindable], что штопор без бутылки :)

Upd: Работает только с публичными свойствами (касается так же вложенных объектов). Вложенные объекты так же должны быть снабжены метатегом RemoteClass.

Март 24th, 2008 от graann

Продолжу тему затронутую Александром Гаховым в статье Клонирование объектов утилитой ObjectUtil.copy.

Здесь я приведу пример использования registerClassAlias для восстановления объектов определенного класса из SharedObject. Суть проблемы заключалась в том, что помещенные в SharedObject экземпляры определенного класса при перезапуске возвращались, как экземпляры класса Object. Когда я столкнулась с этой проблемой, доступного для понимания примера мне нагуглить не удалось. Перед размещением же поста, я нашла вопрос по этой теме в ruFlex, однако приведенный там пример показался мне не вполне наглядным. Предлагаю вашему вниманию свой пример решения этой проблемы:

XML:

<mx:Application creationComplete="onCreationComplete()" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
  import src.DataObject;
  import flash.net.*;
  
  private var so: SharedObject;
  private var dataObject: DataObject;
 
  
  private function onCreationComplete(): void
  {
    dataObject=new DataObject();
    registerClassAlias('src.DataObject', DataObject);    
    so = SharedObject.getLocal("test");
  }
  
  
  private function dataObjectGeneration(): void
  {
    dataObject.generate();
    ta.htmlText+='GENERATION: '+dataObject.toString()+'\n';
  }
  
  private function saveLocalData(): void
  {
    so.data.DataObject=dataObject;
    so.flush();
    ta.htmlText+='SAVE: '+dataObject.toString()+'\n';
  }
  
  
  
  private function loadLocalData(): void
  {
    so = SharedObject.getLocal('test');
    if(so.data.DataObject!=null)
    {
      dataObject=so.data.DataObject as DataObject;
      ta.htmlText+='LOAD: '+dataObject.toString()+'\n';
    } else {
      ta.htmlText+='LOAD: null\n';
    }
  }
  
]]>
</mx:Script>
<mx:Button x="193" y="27" label="save" id="save_" click="{saveLocalData()}"/>
<mx:Button x="107" y="27" label="generate" id="generate" click="{dataObjectGeneration()}"/>
<mx:Button x="49" y="27" label="load" id="load_" click="{loadLocalData()}"/>
<mx:TextArea x="49" y="57" height="141" width="618" id="ta"/>
</mx:Application>

Собственно сам класс нашего объекта.

  1. ackage src
  2. {
  3.         import mx.formatters.DateFormatter;
  4.        
  5.         public class DataObject
  6.         {
  7.                 public var date: Date;
  8.                 public var random: String;
  9.                
  10.                 public function DataObject()
  11.                 {
  12.                        
  13.                 }
  14.                
  15.                 public function generate(): void
  16.                 {
  17.                         date=new Date();
  18.                         random=""+Math.random()*10000;
  19.                 }
  20.                
  21.                 public function toString():String
  22.                 {
  23.                         var df: DateFormatter=new DateFormatter();
  24.                         df.formatString="JJ:NN:SS DD/MM/YYYY";
  25.                         return "\n  date: "+df.format(date)+"\n  random: "+random;
  26.                 }
  27.         }
  28. }

Прошу прощения за подобное отображение mxml-ины. Если пример вас заинтересует скопируйте его. :)

Январь 31st, 2008 от graann

Путь скинизации посредством css тернист и многотруден. Особенно если каждый стиль требуют собственных скинов для виджетов (иконок, кнопок и т.д). Предположим нам надо подгрузить картинку. Для примера создадим класс наследованный от UIComponent и требующий подгрузки картинки описанной в css. Назовем класс Example.as.

Стили для него описаны в одноименном блоке стиля. (вы разумеется знаете, что стили цепляются к одноименной компоненте автоматом и не требуют каких-то дополнительных директив?)

Казалось бы чего проще?…

XML:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ns1="src.*">
    <!−− так конечно делать не надо, но для примера покатит :) с css будет так же!−−>
    <mx:Style>
        Example{image: Embed("graphics/image.png");}
    </mx:Style>
    <ns1:Example x="42" y="24"/>
</ns1:Example></mx:Application>
  1. package src
  2. {
  3.        import mx.core.UIComponent;
  4.        import mx.controls.Image;
  5.  
  6.        public class Example extends UIComponent
  7.        {
  8.                private var image: Image;
  9.                
  10.                public function Example()
  11.                {
  12.  
  13.                }
  14.                
  15.                override protected function createChildren(): void
  16.                {
  17.                        super.createChildren();
  18.                        image=new Image();
  19.                        image.source=getStyle("image");
  20.                        addChild(image);
  21.                }
  22.                
  23.        }
  24. }

И после компиляции картинку благополучно не видим. Почему? Потому, что по умолчанию ее размеры составляют 0 x 0. Для того чтобы она отобразилась корректно требуется задать ей реальные размеры, каковые нам любезно предоставляют свойства measuredWidth и measuredHeight. Однако актуальные значения ширины и высоты будут доступны только после вызова метода protected function measure(): void UIComponent, о котором доступна подробная информация в хелпе.

Ну и собственно результат:

  1. package src
  2. {
  3. import mx.core.UIComponent;
  4. import mx.controls.Image;
  5.  
  6. public class Example extends UIComponent
  7. {
  8.         private var image: Image;
  9.        
  10.         public function Example()
  11.         {
  12.         }
  13.                
  14.         override protected function createChildren(): void
  15.         {
  16.                 super.createChildren();
  17.                 image=new Image();
  18.                 image.source=getStyle("image");
  19.                 addChild(image);
  20.         }
  21.  
  22.         override protected function measure():void
  23.         {
  24.                 super.measure();
  25.                 image.setActualSize(image.measuredWidth, image.measuredHeight);
  26.         }
  27.        
  28. }

Следует отметить, что подобных проблем с размерами не возникает в mxml-e.

Сентябрь 7th, 2007 от graann Сентябрь 6th, 2007 от graann

Сегодня у Константина Палыча день рождения!

Поздравляю!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Счастье у тебя уже есть, поэтому дальнейших творческих узбеков тебе, Костик, и чтобы твое здоровье тебе ни в чем не отказывало! :)

Август 16th, 2007 от graann

По ряду причин была вынуждена установить на свою рабочую машину Vista. Расскажу о тех проблемах, с которыми столкнулась в ходе установки flex builder2 под Vista. Сразу оговорюсь переходить на 3-й builder мы не стали т.к он бета и показался нам не стабильным.

Проблема раз. Попытка установить второй билдер под eclipse 3.3:

Проблема два. Вернее легкое неудобство. В процессе установки инсталятор отказался демонстрировать контролы. Просто не отображал. Устанавливать пришлось на автопилоте руководствуясь подсознанием. Установила. Честно признаюсь не с первого раза.

Update установила.

Проблема три. SVN отказался дружить с подцепленым проектом. Проблема довольно специфическая, врядли у кого-то повторится, поэтому подробно останавливаться на ней не буду. Починила.

Установила subclips.

Последняя капля. Эклипс периодически вылетал с предупреждением следующего вида

В debugg-режиме с прерываниями он вылетал постоянно. Переставляла builder и java. Не помогло.

Август 16th, 2007 от graann

Счастья, здоровья, хорошего аппетита, трудовых свершений, а главное, крепких нервов в совместной работе с твоей горячо любимой мной :)

Август 13th, 2007 от graann

На протяжении довольно долгого времени я пользовалась OmeaReader-ом. Была я вполне счастлива и довольна, пока в один прекрасный день omea не задергался в конвульсиях и не умер прихватив с собой всю мою базу. Довольно неприятное обстоятельство, особенно учестывая, что легко восстановить мне ее не удалось. В начале не помогла перезагрузка, а потом и переустановка. Спас почищенный реестр, но рисковать так более я готова не была. Возникла потребность в поиске другого RSS-reader-а, результатом чего и стал этот пост. Обзоров было уже довольно много. И зачастую они весьма противоречивы. Я же только поделюсь с вами своим абсолютно субъективным мнением.

Mozilla Thunderbird. 2.0.0.6

Я русский бы выучил только за то, что им разговаривал Ленин.

Клиент бесплатный. Mozilla Firefox был и остается моим самым любимым браузером. Разумеется на Thunderbird я обратила свое пристальное внимание и… И мои надежды не оправдались. Как rss-клиент мне он показался глючным, неудобным и, что самое неприятное, он теряет каналы. Потерянные каналы не отображаются в списке подписок, но Thunderbird свято верит, что они где-то есть и при попытке повторной подписи выкидывает эксепшен. Потерянных каналов было только 2, но мне как-то хватило. Кроме того, порадовала приятная необходимость всякий раз при запуске подтверждать пароли на все каналы требующие аутентификации. Подтверждать нажатием кнопочки enter. Однако, если таковых каналов у вас не один, мягко говоря, это начинает нервировать. Отключить этот бонус мне не удалось.
И тем не менее пока Thunderbird остался моим основным почтовым клиентом.
ЗЫ: В ходе изысканий был найден, приятный, на мой взгляд, плагин сворачивающий Firefox и Thunderbird в трей

Microsoft Office Outlook 2007

слишком много букв

Буду краткой. Не халява. Запутанный и перегруженный интерфейс. Слишком умный для меня. Мой моск, в плане продвинутости, не готов с ним конкурировать. Не нравится.

Abilon 2.5.3 b 196

и все бы было хорошо, если бы не… глюки

Бесплатный. Легкий и быстрый. Вполне удобный. Все бы с ним хорошо, если бы не одна небольшая фигня. Отказался правильно парсить жж-шные посты. :)

FeedDemon 2.3.0.10

счастье есть!

Не халява. Но выбрала я именно его. Боюсь даже, что он затмил в моих глазах OmeaReader в его неглючные времена. Он нравится мне всем, кроме стоимости. :) Не буду вдаваться в пространное описание тем более что таковых в сети и без моего предостаточно. Заинтересованные могут почитать о нем например тут и не только о нем тут

:: Следующие >>

Graann`s blog
flash, flex и все, что придет в голову

Сентябрь 2010
Пн Вт Ср Чт Пт Сб Вс
 << <   > >>
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      

О блоге

С назначением блога можно ознакомиться здесь

Идейным вдохновителем и по совместительству куратором блога является Сonstantiner, за что ему огромный респект и уважуха! Впрочем не только за это :)

Поиск

powered by b2evolution free blog software


Design downloaded from Zeroweb.org
Website templates, layouts, and website tools for FREE!
Free short URL services from urlSNIP.