WPF Hint
От: capgoat  
Дата: 31.10.09 21:38
Оценка:
Здравствуйте, VladD2, Вы писали:

Сорри за задержки, вечно не хватает времени.
Что нового в новой версии:
1. Появились свойства ProportionalFontFamily, ProportionalFontSize — для тэга code,
FixedFontFamily, FixedFontSize — для остальных
2. Новая обработка параметров
<params>
<param attrs="[NotNull]" name="loc" typeShortName="Location" typeFullName="Nemerle.Compiler.Location">description</param>
<param .../>
<param .../>
</params>
Тут есть замечания:
— как обрабатывать attrs(примерчик бы)
— description реализован как сабхинт к name и к type, может надо было как-то иначе
— name и type некликабельные, т.е. для них нельзя задать handler, а может оно и не надо

Парсинг:
Основная сложность возникает из-за тэга pre.
Вне его все пробельные символы должны заменяться на пробел(эмуляция html).
Кроме того, после парсинга в выходной структуре для построения UI этого тэга не должно быть.
В предыдущей версии были некоторые сложности из-за динамического params,
сейчас этот код благополучно убран.

Краткое описание классов:
класс RootText — содержит исходный текст в виде массива символов
класс ParseToken — базовый класс для TextToken, ElementToken, содержит границы элементов в исходном тексте
класс TextToken — представляет часть исходного текста (а-ля XText),
класс ElementToken — содержит распарсенные аттрибуты, подэлементы (TextToken или ElementToken )
класс RootToken — распарсивает исходный текст в токены
класс HintParser — основной класс, создает RootToken, затем как постобработка, идет удаление пробельных символов и тэга pre.

Также добавил немного комментов и почистил код.
Надеюсь теперь будет полегче с пониманием.

PS В svn коммить лучше сам

02.11.09 23:13: Ветка выделена из темы Кто может написать контрол &mdash; крутой хинт?
Автор: VladD2
Дата: 18.08.09
— VladD2
Re: WPF Hint
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.11.09 19:46
Оценка:
Здравствуйте, capgoat, Вы писали:

C>Что нового в новой версии:

C>1. Появились свойства ProportionalFontFamily, ProportionalFontSize — для тэга code,
C>FixedFontFamily, FixedFontSize — для остальных
C>2. Новая обработка параметров
C><params>
C><param attrs="[NotNull]" name="loc" typeShortName="Location" typeFullName="Nemerle.Compiler.Location">description</param>
C><param .../>
C><param .../>
C></params>
C>Тут есть замечания:
C>- как обрабатывать attrs(примерчик бы)
C>- description реализован как сабхинт к name и к type, может надо было как-то иначе
C>- name и type некликабельные, т.е. для них нельзя задать handler, а может оно и не надо

Я тут уже прикрутил прошлую версию:
http://www.rsdn.ru/forum/prj.nemerle/3587213.1.aspx
Автор: VladD2
Дата: 30.10.09

http://www.rsdn.ru/forum/prj.nemerle/3589689.1.aspx
Автор: VladD2
Дата: 02.11.09


Причем пришлось несколько изменить код. Так что теперь нужно слить твои и мои изменения.

Итак, что я сделал.
1. Я отключил парсинг параметров с помощью регексов. Вместо этого я стал задавать параметры явно, с помощью тегов <params>, <pname> и <ptype>. Сразу же выяснилось, что "табличное" форматирование (т.е. поддержка котлонок) нужно не только для параметров, но и в других местах. Так что нужно назвать это дело как-то нейтрально и реализовать поддержку более чем двух колонок (обычно нужно будет 2-4, но лучше если не фиксировать их количество явно).

2. Я изменил формат тега <hint>. Теперь он выглядит так:
<hint value='текст отображаемый вместо данного тега' key='ключ' handler='обработчик'>ХМЛ вложенного хинта</hint>

Суть в том, что вложенный хинт может быть столь же навороченным как и основной. Так что его разметку просто нельзя запихать в значение атрибута. А вот текст который отображается вместо тега вложенного хинта как раз без проблем кладется в атрибут.
Что такое handler я думаю объяснять не надо. А вот key нужно пояснить.
Дело в том, что хинты (по крайней мере) для типов нельзя сформировать сразу. Если попытаться это сделать, то в лучшем случае можно получить очень объемный код хинта, а в худщем получить зацикливание. Так вот поле key позволяет не задавать текст хинта сразу, а подгружать его по мере надобности (когда пользователь подводит курсор мыши к активной зоне).
Для работы этого нового ключа я добавил в class Hint поле:
private Func<string, string> _getHintContent;

которое задается параметром метода Show. Кстати, я добавил еще одну перегрузку этого метода:
public void Show(IntPtr owner, Rect placementRect, Func<string, string> getHintContent, string text)

так как удобнее задавать эти параметры при каждом вызове, а пихать их в свойства.
Типичный обработчик передаваемый через это поле выглядит так:
def makeTypeStr(key : string) : string
{
  def ty = idToTypeMap[int.Parse(key)];
  def cnv = Convert();
  cnv.ConvertTypeName = convertTypeName;
  $"<hint>$(cnv.FixedTypeToString(ty))</hint>"
}

т.е. ищет тип в ассоциативном массиве и генерирует хинт для найденного типа. Ключ при этом генерируется как простая последовательность чисел:
mutable currentId = 1;
def idToTypeMap = Hashtable();
def getTyId(ty) : int
{
  currentId++;
  idToTypeMap.Add(currentId, ty);
  currentId
}

def convertTypeName(ty, name)
{
  $"<font color='DarkCyan'><hint value='$name' key='$(getTyId(ty))' /></font>"
}

понятно, что если задан атрибут key, то тело тега <hint> игнорируется (так как оно получается динамически).

C>Парсинг:

C>Основная сложность возникает из-за тэга pre.
C>Вне его все пробельные символы должны заменяться на пробел(эмуляция html).
C>Кроме того, после парсинга в выходной структуре для построения UI этого тэга не должно быть.
C>В предыдущей версии были некоторые сложности из-за динамического params,
C>сейчас этот код благополучно убран.

Я тоже его закоментировал. Вместо этого дабавляю теги <params>, <pname> и <ptype> вручную.
Кстати, оказалось, что табличный вывод удобен не только для отображения параметров, так что логично было бы обобщить этот прием. Нужно что-то типа табулируемого при переносе текста. Так чтобы в нем было от одной, до четырех колонок (лучше конечно чтобы этот дело вычислялось динамически или задавалось бы атрибутом). Я вижу это себе примерно так:
<tbl>
  <row><col><keyword>this</keyword></col><col>param1</col><col>: Type1, </col></row>
  <row><col>[NotNull]</col>              <col>param2</col><col>: Type2</col></row>
</tbl>

Естественно, что все лишние пробелы должны игнорироваться (как в HTML).

C>Краткое описание классов:

C>класс RootText — содержит исходный текст в виде массива символов

А зачем он?

C>Также добавил немного комментов и почистил код.


Очень жаль, что все это не в той весрии, что я уже использую. Не мог бы ты их слить? Но оставить мой вариант тега hint.

C>Надеюсь теперь будет полегче с пониманием.


Я тоже надеюсь.

C>PS В svn коммить лучше сам


Во с этим проблема.
Я все же не доконца понимаю все вещи. Особенно там где чистых ВПФ. Все эти зависимые свойства для меня темный лес.
Я чтобы прикрутить новый обработчик был вынужден протащить его через твой код анализа ХМЛ (в качестве параметра ко всем функциям) и это потому, что я не смог разобраться с тем как реализовать обратный вызов (колбэк) через механизмы ВПФ.

ЗЫ

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

CallbackOnCollectedDelegate was detected
Message: A callback was made on a garbage collected delegate of type 'WpfHint!WpfHint.Win32+Callback::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.

по всей видимости — это что-то из химии связанной с сабласиньем окна (перехватом его очереди сообщений). Но я могу ошибаться. Надо это как можно скорее пофиксить!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: WPF Hint
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.11.09 20:19
Оценка:
Здравствуйте, capgoat, Вы писали:

Да... Совсем забыл!

Есть еще одна проблема. Даже две:
1. Когда текст строки в хинте превышает длину окна, то он не переносится, а вылезает за пределы хинты (обрезается).
2. При тех же условиях сам хинт (его левая часть) уходит за пределы экрана тем самым делая часть текста не видной.

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

Кстати, надо учитывать, что монитор может быть не один. Так что все расчеты нужно производить относительно текущего монитора.

Собственно свойство WrapWidth как таковое не нужено. Его значение должно автоматом браться из ширины текущего экрана. Другими словами хинт должен быть не больше текущего экрана.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: WPF Hint
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.11.09 20:23
Оценка:
Здравствуйте, capgoat, Вы писали:

И еще одно.

Первая загрузка хинта нереально долкая .

Хорошо бы как-то ее оптимизировать.

Можно попробовать создать отдельный поток (ГУИ поток) в котром создать очередь выборки сообщений с формочкой, вывести ее за пределы экрана (чтобы видно не было) и сразу же показать хинт. Тогда инициализация WPF пройдет в фоне и когда пользователь захочет посмотреть хинт, то ему не придется ждать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: WPF Hint
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.11.09 20:38
Оценка:
Здравствуйте, capgoat, Вы писали:

И я тут еще вот что нарыл:
http://support.microsoft.com/kb/280582
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: WPF Hint
От: capgoat  
Дата: 05.11.09 16:06
Оценка:
Здравствуйте, VladD2, Вы писали:

Что ж, давай будем сливать.
Но уточним несколько моментов:
1. Нужен ли тэг <param name=.../>, и если да, то что в нем изменить или оставить как есть?
2. "Табличное" форматирование — пара юзкейсов не помешало бы, должно быть статическим (как в html) или динамическим (как с параметрами)?
3. <hint>
На самом деле разметку можно засунуть и в атрибут, например так: "<a " + new XAttribute("attr", "<b>bb</b>").ToString() + ">aa</a>".
А подгрузку хинта я бы наверное сделал через событие, к-е возникало бы при наведении мышки на активный участок, примерно так:
        // PreviewHint event handler
        void OnPreviewHint(PreviewHintArgs args)
        {
            // analyze args.Key
            // if (valid)
            // {
            //  args.HintText = ...
            //  args.ShowHint = true
            // }
            // else            
            //  args.ShowHint = false
        }

        class PreviewHintArgs
        {
            public string Key { get; private set; }
            public string HintText { get; set; }
            public bool ShowHint { get; set; }
        }

4. Первая загрузка хинта
Мне кажется можно проинициализировать WPF, создав например простое невидимое окно и сразу его закрыв, при старте nemerle.
5. Целая секунды до закрытия хинта мне кажется многовато(к слову, введение этого таймера была вынужденная мера, из-за того, что некоторые св-ва не успевали вовремя обновляться)
6. CallbackOnCollectedDelegate was detected
Эту проблему я знаю, но по идее она не должна возникать, т.к. делегаты специально хранятся в private fields, возможно я что-то упустил.
Re[3]: WPF Hint
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.11.09 17:07
Оценка:
Здравствуйте, capgoat, Вы писали:

Ты не мог бы связаться со мной по скайпу или MSN-у?

А то так очень уж не интерактивно получается?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: WPF Hint
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.11.09 17:09
Оценка:
Здравствуйте, capgoat, Вы писали:

...

Мой Skype VladD2 в Windows Live Messendger тоже.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: WPF Hint
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.11.09 17:53
Оценка:
Здравствуйте, capgoat, Вы писали:

C>Что ж, давай будем сливать.

C>Но уточним несколько моментов:
C>1. Нужен ли тэг <param name=.../>, и если да, то что в нем изменить или оставить как есть?

Скажем так. Он нужен но немного в другом виде. Ниже я приведу полный список уточненных требований. В данном случае нам нужно обобщить данный тег. Назовем его просто <row>, а внешний тег <tabulated>. Дело в том, что он может применяться не только для параметров.

C>2. "Табличное" форматирование — пара юзкейсов не помешало бы, должно быть статическим (как в html) или динамическим (как с параметрами)?


ОК. Ниже будет пример.

C>3. <hint>

C>На самом деле разметку можно засунуть и в атрибут, например так: "<a " + new XAttribute("attr", "<b>bb</b>").ToString() + ">aa</a>".

Это не удобно, так как внутри так же будут встречаться кавычки. Тем более, что я уже подправил исходную реализацию и она уже обеспечивает требуемое поведение.

C>А подгрузку хинта я бы наверное сделал через событие, к-е возникало бы при наведении мышки на активный участок, примерно так:


Это я уже сделал, и не через событие, а просто через делегат. Так значительно удобнее. И вообще, всю динамически меняемую информацию удобнее задавать через параметры метода Show, а не через свойства. В свойствах должны быть общие настройки вроде шрифтов используемых по умолчанию.

C>
C>        // PreviewHint event handler
C>        void OnPreviewHint(PreviewHintArgs args)
C>        {
C>            // analyze args.Key
C>            // if (valid)
C>            // {
C>            //  args.HintText = ...
C>            //  args.ShowHint = true
C>            // }
C>            // else            
C>            //  args.ShowHint = false
C>        }


Для сравнения, как это делается сейчас:
if (Service.ShowHint(view, hintSpan, tipInfo.GetHintContent, hintText))
  return (int)TipSuccesses2.TIP_S_NODEFAULTTIP;

При этом код формирующий функцию находится в совершенно другом месте (даже другой сборке):
    public GetDelayedHintHendler() : Func[string, string]
    {
      def makeTypeStr(key : string) : string
      {
        AddNamespaces  = true;
        ExpandTypeArgs = false;
        def ty = _idToTypeMap[int.Parse(key)];
        
        def makeDelegateExt(ti)
        {
          def m = ti.LookupMember("Invoke").Head;
          "<lb/>Signature: " + FixedTypeToString(m.GetMemType()) + "<lb/>"
          + "Inferred: " + TypeVarToString(ty.TypeOfMember(m))
        }
        
        def baseTypesExt(ti : TypeInfo, baseTypeName = "Base type") : string
        {
          def implementsInfo(itfs : list[MType.Class]) : string
          {
            def plural = if (itfs.Length > 1) "s" else "";
            def prompt = if (ti.IsInterface) $"Base interface$plural" else "Implements";
            if (itfs.IsEmpty) ""
            else $<#<lb/>$prompt: ..$(itfs; ", "; FixedClassTypeToString)#>
          }
          def old = AddNamespaces;
          AddNamespaces = false;
          def itfs1 = ti.GetDirectSuperTypes();
          def baseType = ti.BaseType;
          def itfs = if (baseType == null) itfs1 else itfs1.Tail;
          def res = 
            if (baseType != null)
              $"<lb/>$baseTypeName: " + TypeVarToString(ty.GetInstantiatedSuperType(baseType)) + implementsInfo(itfs)
            else implementsInfo(itfs);
          
          AddNamespaces = old;
          
          res
        }
        
        def (kind, ext) = 
          match (ty)
          {
            | Class(ti, _args) => 
              def (kind, ext) =
                if      (ti.IsDelegate)  ("delegate ", makeDelegateExt(ti))
                else if (ti.IsModule)    ("module ", "")
                else if (ti.IsValueType) ("value type ", "")
                else match (ti.GetTydecl())
                {
                  | Class     with kind = "class "
                  | Interface with kind = "interface " => (kind, baseTypesExt(ti))
                  | VariantOption => 
                    def old = AddNamespaces;
                    AddNamespaces = false;
                    def flds = ti.GetFields(BFlg.DeclaredOnly | BFlg.Instance | BFlg.Public)
                                 .Map(f => $"$(f.Name) : $(TypeVarToString(ty.TypeOfMember(f)));");
                    def flds = if (flds.IsEmpty) "" else  $<#<lb/>Fields: ..$flds#>;
                    AddNamespaces = old;
                    ("variant option ", flds + baseTypesExt(ti, "Declaring variant"))
                      
                  | Variant(members) when members.IsEmpty => ("variant ", baseTypesExt(ti))
                  | Variant(members) =>
                    def old = AddNamespaces;
                    AddNamespaces = false;
                    def ops = members.Map(o => FixedClassTypeToString(o.GetMemType()));
                    AddNamespaces = old;
                    ("variant ", $<#<lb/>Variant options: ..$ops<lb/>$(baseTypesExt(ti))#>)
                    
                  | Enum              => ("enum ", "")
                  | Alias             => assert(false);
                };
              def obsolete = if (ti.IsObsolete) "[Obsolete] " else "";

              (obsolete + "<keyword>" + Utils.MakeAccessModifiers(ti) + kind + "</keyword>", ext)
            
            | TyVarRef       => ("type parameter ", "")
            | Fun            => ("function type ", "")
            | Tuple          => ("tuple ", "")
            | Array(_, rank) => ($"$rank dimention ", "")
            | Ref            => ("ref parameter ", "")
            | Out            => ("out parameter ", "")
            | Void           => ("", "")
            | Intersection   => ("", "")
          };
        
        $"<hint>$kind$(FixedTypeToString(ty))$ext</hint>"
      }
      
      makeTypeStr
    }


C>        class PreviewHintArgs
C>        {
C>            public string Key { get; private set; }
C>            public string HintText { get; set; }
C>            public bool ShowHint { get; set; }
C>        }
C>


Вот это все совсем лишнее! События — это навязанная Майкрософтом глупость. Целая идеология навернута на пустом месте. Функции высшего порядка проще и удобнее. Со временем это поймут и в Майкрософт... я надеюсь. Врос просто. На входе ключ, на выходе значение. Как там что внутри устроено — это детали реализации. Никакие другие параметры не нужны.
И главное! Имеративщине без особой надобности — это зло! Не надо делать модифицируемые объекты когда можно просто возвратить текст из функции.

C>4. Первая загрузка хинта

C>Мне кажется можно проинициализировать WPF, создав например простое невидимое окно и сразу его закрыв, при старте nemerle.
C>5. Целая секунды до закрытия хинта мне кажется многовато(к слову, введение этого таймера была вынужденная мера, из-за того, что некоторые св-ва не успевали вовремя обновляться)
C>6. CallbackOnCollectedDelegate was detected
C>Эту проблему я знаю, но по идее она не должна возникать, т.к. делегаты специально хранятся в private fields, возможно я что-то упустил.

Возникала. Но похоже я ее уже сам пофиксил. Дело было в том, что ты не сделал финализатор у своего объекта. Далее получалось следующее. Происходит какое-нибудь исключение или еще что-то и не вызывается событие в котором ты делаешь АнСабКласс от окна. Далее сборка мусора и первый же вызов оконной функции приводит к схлопыванию студии.

Кроме того оказалось, что к схлопыванию приводит любое исключение внутри оконной функции. Я поставил обработчик исключений перехваливающий все исключения долетевшие до оконной функции.
Вообще с этим перехватом проблем было много. Вроде бы я их все пофиксил. Посмотри на мои изменения:
http://code.google.com/p/nemerle/source/detail?r=8428
http://code.google.com/p/nemerle/source/detail?r=8427
http://code.google.com/p/nemerle/source/detail?r=8426
http://code.google.com/p/nemerle/source/detail?r=8425


Теперь обещанное описание требуемых возможностей


Опишу задачу.

1. Текст длинных строк в ней не переносится на другие сроки из-за чего он попросту обрезается.
2. На мой взгляд реализация у него слишком переусложнена. Происходит это, на мой взгляд, из-за того, что вместо возможностей WPF в ней используется подход который можно ласково назвать "закат солнца вручную". То есть, вместо использования контролов который форматировали бы текст в ней применяется ручной подсчет размеров (сразу оговорюсь, что в WPF я пока понимаю мало, так что могу ошибаться).

Собственно интересно послушать предложения (от самых общих, до конкретных кусков кода) о том как бы вы (естественно, те кто понимает что-то в WPF) реализовали функциональность которая будет описана ниже. Естественно, приветствуется конкретный код .

Итак, задача:

Форматирвоание

В тексте хинта разметка задается с помощью тегов а-ля XML/HTML:
<keyword></keyword> — задает синий цвет букв для своего содержимого.
<b></b> — задает жирный шрифт для своего содержимого.
<hint value='отображаемое значение' key='ключ для считывания содержимого вложенного хинта'/>
<hint value='отображаемое значение'>Содержимое вложенного хинта в котором так же возможна разметка</hint>

Тег hint определяет вложенных хинт. Значение атрибута value отображается в основном хинте. Когда к нему подводится курсор мыши появляется вложенных хинт. Содержимое вложенного хинта берется или из содерижмого тега hint (если не задан атрибут key), или из обработчика события (которому передается значение из атрибута key). Второй вариант служит для организации отложенной (ленивой) инициализации содержимого вложенных хинтов.
<type></type> — задает цвет DarkCyan букв для своего содержимого.
возможны и другие варианты. Главное что сейчас нужно понять, что разметка задается тегами.
Некоторый текст вначале
<tabulated>
  <row><col>текст первой колонки</col><col>текст второй колонки</col></row>
  <row><col>текст первой колонки второй стоки</col><col>текст второй колонки второй стоки</col></row>
  ...
</tabulated>
текст в конце

Это весьма не обычное решение. Прошу обратить на него больше внимания.
Работает оно так. Если текст всех элементов может быть размещен на одной строке (т.е. его длинна не привысит ширины экрана), то текст должен быть выведен в одну строку. Если ширина текста превышает ширину экрана, то текст должен не просто перетекать на другую строук, а автоматически выравниваться в стиле "невидимой таблицы". Чтобы стало понятнее продемонстрирую сказанное на примере. Предположим у нас есть сигнатура метода:
public GetInheritors([NotNull]filePath : string, line : int, col : int) : array [GotoInfo]

Мы размечаем ее следующим образом:
public GetInheritors(
<tabulated>
   <row><col>[NotNull]</col> <col>filePath </col> <col>: string, </col></row>
   <row><col></col>          <col>line </col>     <col>: int, </col></row>
   <row><col></col>          <col>col </col>      <col>: int</col></row>
<tabulated>
) : array [GotoInfo]

При этом внутри всего это дела могут встречаться и другие теги (теги форматирования изменяющие шрифт).
Если чистый текст полученный после удаления всех этих тегов, т.е.:
public GetInheritors([NotNull]filePath : string, line : int, col : int) : array [GotoInfo]

превышает ширину экрана (или скажем более абстрактно — некое предельное значение), то текст должен быть выведен в виде:
public GetInheritors(
  [NotNull] filePath : string, 
            line     : int, 
            col      : int
) : array [GotoInfo]/c#]

Собственно табличное форматирование нужно не только для параметров. Многие списки могли бы быть оформлены таким же образом.
<pre></pre> — тест в этом теге должен выводиться моноширинным шрифтом (в котором все символы имеют одинаковую ширину) и пробелы не должны игнорироваться. Данный формат применяется для вывода примеров кода. При этом в нем должны поддерживаться как теги форматирования (цвет и жирный), так и подхинты.

Перенос строк


В хинте могут отображаться данных в следующих формах:
1. Простой текст. Он должен "перетекать", т.е. если текст абзаца не помещается в шириру экрана, он (текст) должен быть автоматически перенесен на другую строку.
2. Табулированный текст. Его поведение я описал выше. Он должен быть в одну стоку если не превышает ширину экрана и таблично отформатированный и перенесен если не укладывается в одну строку.
3. Списки. Нечто вроде <ul><li>...</li><li>...</li>...</ul> в HTML. Каждый элемент отображается на отдельной строке и предваряется точкой — "•".
4. Список со скрываемыми, вложенными элементами. Это нужно для отображения сообщений об ошибках имеющих зависимые пункты. Скажем если у нас есть неоднозначность (несколько перегрузок), то каждая из перегрузок будет иметь ряд (от одного до нескольких) вложенных (зависимых) сообщений об ошибках в которых будет сказано почему данная перегрузка не подошла. Такие сообщения по умолчанию имеет смысл скрывать, а выводить только верхний уровень (в котором перечисляются только сообщения о том, какие перегрузки не прошли типизацию). Если пользователь захочет, он нажмет на плюск и увидит вложенные сообщения. В общем, это что-то вроде вложенного дерева элементы которого раскрываются (или схлопываются, если она уже были раскрыты) при нажатии.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: WPF Hint
От: capgoat  
Дата: 22.11.09 15:52
Оценка: 132 (1)
Здравствуйте, VladD2, Вы писали:

Новая версия
Re: WPF Hint: Размер шрифта
От: Aleх  
Дата: 24.11.09 20:08
Оценка:
Зачем такой большой? Лучше сделать такой же, какой установлен для кода.
Re[2]: WPF Hint: Размер шрифта
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.11.09 16:23
Оценка:
Здравствуйте, Aleх, Вы писали:

A>Зачем такой большой? Лучше сделать такой же, какой установлен для кода.


За тем, что WPF текущей версии не умеет качественно выводить мелкий код.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: WPF Hint: Размер шрифта
От: Aleх  
Дата: 25.11.09 16:55
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Aleх, Вы писали:


A>>Зачем такой большой? Лучше сделать такой же, какой установлен для кода.


VD>За тем, что WPF текущей версии не умеет качественно выводить мелкий код.

В 2010 вижуал студии местами это как то же сделали. Если не смотреть на меню, то там везде рендеринг текста нормального качества. Или там только меню WPF'ное?
Re[4]: WPF Hint: Размер шрифта
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.11.09 17:15
Оценка:
Здравствуйте, Aleх, Вы писали:

VD>>За тем, что WPF текущей версии не умеет качественно выводить мелкий код.

A>В 2010 вижуал студии местами это как то же сделали. Если не смотреть на меню, то там везде рендеринг текста нормального качества. Или там только меню WPF'ное?

2010-ой студии используют новую, еще не выпущенную, версию WPF в которой этот момент специально оптимизировался.
http://rsdn.ru/forum/dotnet.gui/3587452.1.aspx
Автор: Кирилл Осенков
Дата: 31.10.09
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.