スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#雑記 SimpleFormConverter(4)

 今回は最後に残ったControls.Add部分を定義します。 
 
フラット化されたソースでControls.Addの部分は例えば次のような形になります。 
 
/*102*/            splitContainer1.Panel1.Controls.Add(panel1); 
/*103*/            splitContainer1.Panel1.Controls.Add(listBox1); 
/*107*/            splitContainer1.Panel2.Controls.Add(monthCalendar1); 
/*108*/            splitContainer1.Panel2.Controls.Add(tabControl1); 
/*153*/            tabControl1.Controls.Add(tabPage1); 
/*154*/            tabControl1.Controls.Add(tabPage2); 
/*163*/            tabPage1.Controls.Add(textBox1); 
/*215*/            mainForm.Controls.Add(splitContainer1); 
/*216*/            mainForm.Controls.Add(menuStrip1); 
 
今回の変換コードでは、102,103のようなコードは一つにして、 
 
let f2c x = x :> System.Windows.Forms.Control  
[ f2c panel1; f2c listBox1] |> List.iter(fun cnt -> splitContainer1.Panel1.Controls.Add cnt) 
 
というように変換したいと思います。 
 
ではまずは getInnerComp フラット化されたソース "panel1"等で 
 "[ f2c splitContainer1 ]  
 |> List.iter(fun cnt -> panel1.Controls.Add cnt)"が返るような関数を定義します。 
  
 > let getInnerComp (flatten_source:string) (containerName:string) = 
    let rgStr = containerName + "\.Controls\.Add\((?<InnerComp>[^\)]+)" 
    let rg = new Regex (rgStr) 
    let matchCol = rg.Matches (flatten_source) 
    let innerCompsSeqStr = //seq ["checkBox2"; "checkBox1"]等の値となる 
         seq{ 
            for mc in matchCol do 
                yield ("f2c " + (mc.Groups.["InnerComp"].Value))  
        } 
    let joinedInnerCompsStr = String.Join ("; ", innerCompsSeqStr) 
    "[ " + joinedInnerCompsStr + "] |> List.iter(fun cnt -> " + containerName + ".Controls.Add " + "cnt)" ;; 
 
val getInnerComp : string -> string -> string 
 
ではテストです。 
 
> getInnerComp formFlattenText "splitContainer1.Panel1";; 
val it : string = 
  "[ f2c panel1; f2c listBox1] |> List.iter(fun cnt -> splitContainer1.Panel1.Controls.Add cnt)" 
   
次になんらかのコンポーネントを含んでいるコンポーネントを抽出して、一意化してから、上の関数getInnerCompを利用し、すべてのControls.Add部分を変換する関数getContAddStrsの定義です。 
 
> let getContAddStrs (flatten_source:string) = 
    let rgStr = "(?<ContinerName>[\w\.]+)\.Controls\.Add" 
    let rg = new Regex (rgStr) 
    let matchCol = rg.Matches flatten_source 
    let containerSeq = //seq ["panel1"; "form1"]等の値となる 
         seq{ 
            for mc in matchCol do 
                yield  (mc.Groups.["ContinerName"].Value)  
        } 
         
    let containerSet = Set.ofSeq  containerSeq //Setを利用して一意化する    
    let sb = new System.Text.StringBuilder() 
    for container in containerSet do 
        sb.Append((getInnerComp flatten_source container) + "\n") |> ignore 
    sb.ToString();; 
 
val getContAddStrs : string -> string 
 
テストです。 
 
> getContAddStrs formFlattenText;; 
val it : string = 
  "[ f2c splitContainer1; f2c menuStrip1] |> List.iter(fun cnt -> mainForm.Controls.Add cnt) 
[ f2c panel1; f2c listBox1] |> List.iter(fun cnt -> splitContainer1.Panel1.Controls.Add cnt) 
[ f2c monthCalendar1; f2c tabControl1; f2c statusStrip1; f2c button1] |> List.iter(fun cnt -> splitContainer1.Panel2.Controls.Add cnt) 
[ f2c tabPage1; f2c tabPage2] |> List.iter(fun cnt -> tabControl1.Controls.Add cnt) 
[ f2c textBox1] |> List.iter(fun cnt -> tabPage1.Controls.Add cnt) 
[ f2c splitContainer2] |> List.iter(fun cnt -> tabPage2.Controls.Add cnt) 
 
ではこれらを統合してとりあえずの完成版のコードは以下の通りです。 
 
open System 
open System.Text.RegularExpressions 
open System.Windows.Forms 
open System.Drawing 
 
let getFormName (ori_source:string) = 
    let rg = new Regex("this.Name = \"(?<FormName>[\w]+)") 
    let matched = rg.Match(ori_source) 
    (matched.Groups.["FormName"].Value).Trim() 
 
 
let getControlNamesAndType (ori_source:string) = 
    let rg = new Regex("private\s+(?<typeOfComp>[\w|\.]+)\s+(?<name>[\w\.]+)\;") 
    let matchCol = rg.Matches(ori_source) 
    seq{ 
        for mc in matchCol do 
            yield ((mc.Groups.["name"].Value).Trim(), (mc.Groups.["typeOfComp"].Value).Trim()) 
        }   
 
let myReplace (regStr:string) (repStr:string) (oriSrcStr:string)= 
    (new Regex(regStr)).Replace(oriSrcStr,repStr) 
 
let getFlattenSource (ori_source:string) = 
    (getControlNamesAndType ori_source) 
    |> Seq.fold(fun str (name,_)  ->let replacePart = "this." + name 
                                    let newWord = "that." + name 
                                    myReplace replacePart newWord str 
                ) 
                ori_source 
    |> myReplace "this." ("this." + (getFormName ori_source) + ".")  
    |> myReplace "this." ""  
    |> myReplace "that." ""  
 
// getPropNameValueEqualStr フラットソーステキスト "load_btn";;で 
// seq    ["Location = new System.Drawing.Point(21, 12)"; "Name = "load_btn""; 
//         "Size = new System.Drawing.Size(75, 23)"; "TabIndex = 0"; ...]が返る 
 
let getPropNameValueEqualStr (flatten_source:string) (contName:string)  = 
     let rgStr =  contName+"\.(?<PropName>[^\s=]+?)\s*=\s*(?<PropValue>(.|\n)+?)\;" 
     let rg = new Regex (rgStr) 
     let matchCol = rg.Matches (flatten_source) 
     seq{ 
        for mc in matchCol do 
            yield ( (mc.Groups.["PropName"].Value) + " = " + (mc.Groups.["PropValue"].Value)) 
    } 
 
 
//let load_btn= new Button(Location = new Point(21, 12),Name = "load_btn",Size = new Size(75, 23),TabIndex = 0,Text = "Load",UseVisualStyleBackColor = true) 
//let ori_source_rtb= new RichTextBox(Location = new Point(21, 41),Name = "ori_source_rtb",Size = new Size(819, 178),TabIndex = 1,Text = "") 
 
let getConstractStrs (ori_source:string) (flatten_source:string) = 
    let sb = new System.Text.StringBuilder() 
    for (name,ptype) in Seq.append (getControlNamesAndType ori_source) (seq[(getFormName ori_source , "Form")]) do 
        let propNameValueEqualStrSeq = (getPropNameValueEqualStr flatten_source name)  
        let joinedStr = String.Join (",", propNameValueEqualStrSeq) 
        sb.Append("let " + name + "= " + "new " + ptype + "(" + joinedStr + ")" + "\n") |>ignore     
    sb.ToString() |> myReplace "System.Windows.Forms." "" |> myReplace "System.Drawing." "" 
 
//  seq [("Items.AddRange", 
//         "(new object[] { 
//              "りんご", 
//             "いちご"})")]等が返る 
 
let getEachMethodStr (flatten_source:string) (contName:string)  = 
     let rgStr =  contName+"\.(?<MethodName>(\w|\.)+?)\(\s*(?<argValue>(.|\n)*?)\)\;" 
     let rg = new Regex (rgStr) 
     let matchCol = rg.Matches (flatten_source) 
     let methodNameArgValSeq = 
         seq{ 
            for mc in matchCol do 
                yield ( (mc.Groups.["MethodName"].Value).Trim(), "(" + (mc.Groups.["argValue"].Value).Trim() + ")") 
        } 
     methodNameArgValSeq 
     |> Seq.filter (fun (name,_) -> (not (name.Contains "SuspendLayout")) &&  
                                    (not (name.Contains "Controls.Add")) && 
                                    (not (name.Contains "PerformLayout")) && 
                                    (not (name.Contains "ResumeLayout"))) 
 
//"menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 
//            openToolStripMenuItem, 
//            endToolStripMenuItem})|>ignore  
//openToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {......が返る 
 
let getMethodStrs (ori_source:string) (flatten_source:string) = 
    let sb = new System.Text.StringBuilder() 
    for (name,_) in Seq.append (getControlNamesAndType ori_source) (seq[(getFormName ori_source , "Form")]) do 
        for (methodName,arg) in (getEachMethodStr flatten_source name) do 
        sb.Append(name + "." +  methodName + arg +  "|>ignore \n") |> ignore     
    sb.ToString()  
 
//配列部分の変換関数 
let replaceSub (matchResult :System.Text.RegularExpressions.Match) = 
    let tempRes = "( [|" + matchResult.Groups.["part2"].Value + "|] :" +  matchResult.Groups.["part1"].Value + "[]))" 
    tempRes 
    |> myReplace "," ";" 
    |> myReplace "\n" "" 
    |> myReplace "System.Windows.Forms." "" 
    |> myReplace "\s+" " " 
    |> myReplace "object" "obj" 
 
let arrPartsReplace (source:string) = 
    let rg = new Regex("new\s+(?<part1>[\w\.]+?)\[\]\s*\{(?<part2>(.|\n)+?)\}\)") 
    rg.Replace(source, new MatchEvaluator(replaceSub)) 
 
//////System.Windows.Forms.Control型へのキャスト関数 
let strForCast = "let f2c x = x :> System.Windows.Forms.Control \n" 
 
// getInnerComp ソース名 "panel1"等で 
// "[ f2c splitContainer1 ]  
// |> List.iter(fun cnt -> panel1.Controls.Add cnt)"が返る 
let getInnerComp (flatten_source:string) (containerName:string) = 
    let rgStr = containerName + "\.Controls\.Add\((?<InnerComp>[^\)]+)" 
    let rg = new Regex (rgStr) 
    let matchCol = rg.Matches (flatten_source) 
    let innerCompsSeqStr = //seq ["checkBox2"; "checkBox1"]等の値となる 
         seq{ 
            for mc in matchCol do 
                yield ("f2c " + (mc.Groups.["InnerComp"].Value))  
        } 
    let joinedInnerCompsStr = String.Join ("; ", innerCompsSeqStr) 
    "[ " + joinedInnerCompsStr + "] |> List.iter(fun cnt -> " + containerName + ".Controls.Add " + "cnt)"  
 
// "[ splitContainer1 ;menuStrip1] |> List.iter(fun cnt -> mainForm.Controls.Add cnt) 
//[ button3 ;button2] |> List.iter(fun cnt -> panel1.Controls.Add cnt) ...が返る 
let getContAddStrs (flatten_source:string) = 
    let rgStr = "(?<ContinerName>[\w\.]+)\.Controls\.Add" 
    let rg = new Regex (rgStr) 
    let matchCol = rg.Matches flatten_source 
    let containerSeq = //seq ["panel1"; "form1"]等の値となる 
         seq{ 
            for mc in matchCol do 
                yield  (mc.Groups.["ContinerName"].Value)  
        } 
         
    let containerSet = Set.ofSeq  containerSeq //Setを利用して一意化する    
    let sb = new System.Text.StringBuilder() 
    for container in containerSet do 
        sb.Append((getInnerComp flatten_source container) + "\n") |> ignore 
    sb.ToString() 
 
//最終結果を得る 
let getResultStrs (ori_source:string) (flatten_source:string) = 
  (strForCast + (getConstractStrs ori_source flatten_source) +  
    (getMethodStrs ori_source flatten_source )) + (getContAddStrs flatten_source) 
  |> myReplace "([\(\s\)]+\d+)F" "$1.0f"  
  |> arrPartsReplace                                   
 
 
let f2c x = x :> System.Windows.Forms.Control  
let load_btn= new Button(Location = new Point(21, 12),Name = "load_btn",Size = new Size(75, 23),TabIndex = 0,Text = "Load",UseVisualStyleBackColor = true) 
let ori_source_rtb= new RichTextBox(Location = new Point(21, 41),Name = "ori_source_rtb",Size = new Size(819, 178),TabIndex = 1,Text = "") 
let conv_btn= new Button(Location = new Point(21, 225),Name = "conv_btn",Size = new Size(144, 54),TabIndex = 2,Text = "Convert",UseVisualStyleBackColor = true) 
let result_rtb= new RichTextBox(Location = new Point(21, 285),Name = "result_rtb",Size = new Size(819, 254),TabIndex = 4,Text = "") 
let to_clip_btn= new Button(Location = new Point(744, 225),Name = "to_clip_btn",Size = new Size(96, 54),TabIndex = 3,Text = "To Clipborad",UseVisualStyleBackColor = true) 
let error_rtb= new RichTextBox(Location = new Point(173, 241),Name = "error_rtb",Size = new Size(553, 38),TabIndex = 5,TabStop = false,Text = "") 
let label1= new Label(AutoSize = true,Location = new Point(171, 222),Name = "label1",Size = new Size(30, 12),TabIndex = 6,Text = "Error") 
let mainForm= new Form(AutoScaleDimensions = new SizeF(6.0f, 12.0f),AutoScaleMode = AutoScaleMode.Font,ClientSize = new Size(864, 570),Name = "minForm",Text = "SimpleFormConverter Ver0.01") 
[ f2c label1; f2c error_rtb; f2c to_clip_btn; f2c result_rtb; f2c conv_btn; f2c ori_source_rtb; f2c load_btn] |> List.iter(fun cnt -> mainForm.Controls.Add cnt) 
 
load_btn.Click.Add 
    (fun _ -> try 
                let ofd = new OpenFileDialog(Filter = "Designer.csファイル(*.Designer.cs)|*.Designer.cs|すべてのファイル(*.*)|*.*") 
                if(ofd.ShowDialog() = DialogResult.OK) then 
                    use sr = new System.IO.StreamReader(ofd.FileName) 
                    ori_source_rtb.Text <- sr.ReadToEnd() 
              with 
                | ex -> error_rtb.Text <- ex.Message  
    ) 
 
 
conv_btn.Click.Add 
    (fun _ -> try 
                result_rtb.Text <- (getResultStrs ori_source_rtb.Text (getFlattenSource ori_source_rtb.Text)) 
              with 
                | ex -> error_rtb.Text <- ex.Message  
    ) 
 
to_clip_btn.Click.Add 
    (fun _ -> try 
               result_rtb.Focus() |> ignore 
               Clipboard.SetText(result_rtb.Text) 
              with 
                | ex -> error_rtb.Text <- ex.Message  
    ) 
 
[<STAThread>] 
do Application.Run(mainForm) 
 
適当にいじって遊んでみてみてください。改変等歓迎です。 
もしよければ改変版できたらブログ等にアップして、教えてください。 
 
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。